下面我们就来分析上图所示的内容.
1. 对照源码和上图, 我们来看第一次调用
// 第一次, 调用实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors // 在所有创世纪的后置处理器中, 只有 internalConfigurationAnnotationProcessor 实现了 BeanDefinitionRegistryPostProcessors 和 PriorityOrdered // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { // 判断beanFactory是否实现了PriorityOrdered接口. 如果实现了,是最优先调用. // 在整个加载过程中,会调用四次BeanDefinitionRegistryPostProcessor, 而实现了PriorityOrdered的接口最先调用 if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { // 调用beanFactory.getBean实例化创世界的类ppName currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); /** * 第一次调用BeanDefinitionRegistryPostProcessors * 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor * 用于进行bean定义的加载 比如我们的包扫描 @import 等 */ invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); // 处理完了,清空currentRegistryProcessors currentRegistryProcessors.clear();
首先, 拿到了所有实现了BeanDefinitionRegistryPostProcessor的后置处理器, 上面我们做过铺垫,只有ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor后置处理器
所以,这里过滤出来的postProcessorNames只有一个,就是ConfigurationClassPostProcessor, 接下来, 判断这个类是否实现了PriorityOrdered 优先排序的接口, 如果实现了, 那么放入到currentRegistryProcessors中, 后面会进行调用.
接下来, 执行invokeBeanDefinitionRegistryPostProcessors
这是第一次调用BeanDefinitionRegistryPostProcessors
2. 第二次调用BeanDefinitionRegistryPostProcessors
// 第二步: 调用实现 Ordered 的 BeanDefinitionRegistryPostProcessors。 // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { // 这时实现了PriorityOrdered.class的postProcessor就不会再被加载进来了, 因为processedBeans.contains(ppName) == true if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { // 将其放入到currentRegistryProcessors, 马上就要被调用 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } // 对所有的处理器进行排序. 调用了Ordered的方法, 会返回排序(一个数字), 然后根据数字排序即可 sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); /** * 第二次调用BeanDefinitionRegistryPostProcessors * 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor * 用于进行bean定义的加载 比如我们的包扫描 @import 等 */ invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear();
第二次调用的时候 ,依然是获取所有的实现了BeanDefinitionRegistryPostProcessor接口的后置处理器, 且这个处理器没有实现过PriorityOrdered也就是没有被上面调用过. 且实现了Ordered接口
这一类添加到currentRegistryProcessors集合中, 然后调用invokeBeanDefinitionRegistryPostProcessors处理
这是第二次调用BeanDefinitionRegistryPostProcessor
3. 第三次调用BeanDefinitionRegistryPostProcessor
// 第三步. 调用没有实现任何优先级接口的 BeanDefinitionRegistryPostProcessor // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. boolean reiterate = true; while (reiterate) { reiterate = false; // 获取 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { // 已处理过的postProcessor不再处理 if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate = true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); /** * 第三次调用BeanDefinitionRegistryPostProcessors * 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor * 用于进行bean定义的加载 比如我们的包扫描 @import 等 */ invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); }
第三次调用的是没有实现过任何排序接口的后置处理器. 并将其放入到currentRegistryProcessors, 然后执行invokeBeanDefinitionRegistryPostProcessors
4. 第四次调用
// Now, invoke the postProcessBeanFactory callback of all processors handled so far. /* * 调用bean工厂的后置处理器 * registryProcessors: 带有注册功能的bean工厂的后置处理器 * regularPostProcessors: 不带注册功能的bean工厂的后置处理器 */ // 调用BeanDefinitionRegistryPostProcessor.postProcessBeanFactory方法----为什么是调用BeanDefinitionRegistryPostProcessor? 因为 // ConfigurationClassPostProcessor 实现了 BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessors invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); // 调用BeanFactoryPostProcessor 自设的(ConfigurationClassPostProcessor没有) invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
ConfigurationClassPostProcessor同时实现了BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessors, 调用的是invokeBeanFactoryPostProcessors
一共进行了4次调用
总结: 优先处理的是实现了PriorityOrdered的后置处理器, 然后调用实现了Order接口的后置处理器, 最后调用了没有实现任何排序方法的后置处理器. 最后调用工厂类方法.
下面我们来具体分析invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
5. 提问: 检验一下是否理解了上面四个步骤
1. ConfigurationClassPostProcessor会调用1234哪几步? 因为ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor,PriorityOrdered, 因此会调用1,4 2. 如果自己定义了一个MyBeanFactoryPostProcessor会调用1234那几步? package com.lxl.www.iocbeanlifecicle; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.stereotype.Component; @Component public class MyBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } } 因为MyBeanFactoryPostProcessor是自定义的, 没有实现任何PriorityOrdered 或者 Order, 因此, 会调用3,4
二. 详细研究第四步, invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);的逻辑.
我们在这一步打个断点, 然后跟着断点一步一步点击进去
这是registryProcessors里面只有一个后置处理器, 就是ConfigurationClassPostProcessor.
然后进入到ConfigurationClassPostProcessor.postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { int factoryId = System.identityHashCode(beanFactory); if (this.factoriesPostProcessed.contains(factoryId)) { throw new IllegalStateException( "postProcessBeanFactory already called on this post-processor against " + beanFactory); } this.factoriesPostProcessed.add(factoryId); if (!this.registriesPostProcessed.contains(factoryId)) { // BeanDefinitionRegistryPostProcessor hook apparently not supported... // Simply call processConfigurationClasses lazily at this point then. processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory); } // 使用 cglib 配置类进行代理, 因为@Bean方法到时候要进行创建Bean的实例. enhanceConfigurationClasses(beanFactory); beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory)); }
这里先看enhanceConfigurationClasses(beanFactory);个方法
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) { Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>(); for (String beanName : beanFactory.getBeanDefinitionNames()) { BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName); Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE); MethodMetadata methodMetadata = null; if (beanDef instanceof AnnotatedBeanDefinition) { methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata(); } if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) { // Configuration class (full or lite) or a configuration-derived @Bean method // -> resolve bean class at this point... AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef; if (!abd.hasBeanClass()) { try { abd.resolveBeanClass(this.beanClassLoader); } catch (Throwable ex) { throw new IllegalStateException( "Cannot load configuration class: " + beanDef.getBeanClassName(), ex); } } } /** * 只有full版配置才会创建cglib代理 * full是怎么来的呢? 我们使用@Configuration注解了, 在加载的时候, 就会设置为full * 当设置为full以后, 我们在调用的时候, 就会创建一个cglib动态代理. * * 为什么要创建动态代理呢? * 动态代理可以保证, 每次创建的bean对象只有一个 * * 那么加@Configuration和不加本质上的区别是什么? * 当在配置类中一个@Bean使用方法的方式引入另一个Bean的时候, 如果不加@Configuration注解, 就会重复加载Bean * 如果加了@Configuration, 则会在这里创建一个cglib代理, 当调用了@Bean方法是会先检测容器中是否存在这个Bean, 如果不存在则创建, 存在则直接使用. */ if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) { if (!(beanDef instanceof AbstractBeanDefinition)) { throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" + beanName + "' since it is not stored in an AbstractBeanDefinition subclass"); } else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) { logger.info("Cannot enhance @Configuration bean definition '" + beanName + "' since its singleton instance has been created too early. The typical cause " + "is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " + "return type: Consider declaring such methods as 'static'."); } configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef); } } if (configBeanDefs.isEmpty()) { // nothing to enhance -> return immediately return; } ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer(); for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) { AbstractBeanDefinition beanDef = entry.getValue(); // If a @Configuration class gets proxied, always proxy the target class beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE); // Set enhanced subclass of the user-specified bean class Class<?> configClass = beanDef.getBeanClass(); Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader); if (configClass != enhancedClass) { if (logger.isTraceEnabled()) { logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " + "enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName())); } beanDef.setBeanClass(enhancedClass); } } }
粗体部分就是判断是否需要进行cglib代理. 进行cglib代理的条件是, beanDefinition中属性configurationClass的值是full. 只有full版配置才会创建cglib代理
那么有下面几个问题:
问题1: full版本配置是什么呢?
我们使用@Configuration注解了, 在加载的时候, 就会将configurationClass属性设置为full.当设置为full以后, 我们在调用的时候, 就会创建一个cglib动态代理.
问题2: 为什么要创建动态代理呢?
动态代理可以保证, 每次创建的bean对象只有一个
问题3:那么加@Configuration和不加本质上的区别是什么?
当在配置类中一个@Bean使用方法的方式引入另一个Bean的时候, 如果不加@Configuration注解, 就会重复加载Bean.如果加了@Configuration, 则会在这里创建一个cglib代理, 当调用了@Bean方法是会先检测容器中是否存在这个Bean, 如果不存在则创建, 存在则直接使用.
问题4:full是怎么来的呢?
这是在上面调用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);接口的时候, 标记的是full还是Lite
下面来看一下源码
在这里一步,执行的时候,进行了这个类是full的还是lite,继续忘下看
此时满足条件的postProcessor只有一个, 那就是ConfigurationClassPostProcessor. 下面直接看ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()方法
前面都是一些条件判断, 重点看processConfigBeanDefinitions(registry);
在这里,这个方法判断了, 这个类是full的还是lite的. 下面直接上代码
/** * Check whether the given bean definition is a candidate for a configuration class * (or a nested component class declared within a configuration/component class, * to be auto-registered as well), and mark it accordingly. * @param beanDef the bean definition to check * @param metadataReaderFactory the current factory in use by the caller * @return whether the candidate qualifies as (any kind of) configuration class */ public static boolean checkConfigurationClassCandidate( BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) { String className = beanDef.getBeanClassName(); if (className == null || beanDef.getFactoryMethodName() != null) { return false; } AnnotationMetadata metadata; // 获取元数据 if (beanDef instanceof AnnotatedBeanDefinition && className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) { // Can reuse the pre-parsed metadata from the given BeanDefinition... metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata(); } else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) { // Check already loaded Class if present... // since we possibly can't even load the class file for this Class. Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass(); if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) || BeanPostProcessor.class.isAssignableFrom(beanClass) || AopInfrastructureBean.class.isAssignableFrom(beanClass) || EventListenerFactory.class.isAssignableFrom(beanClass)) { return false; } metadata = AnnotationMetadata.introspect(beanClass); } else { try { MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className); metadata = metadataReader.getAnnotationMetadata(); } catch (IOException ex) { if (logger.isDebugEnabled()) { logger.debug("Could not find class file for introspecting configuration annotations: " + className, ex); } return false; } } // 判断元数据中是否包含Configuration注解 Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName()); /** * 判断, proxyBeanMethods属性是否为true, 如果为true就是一个完全的类, * 也就是带有@Configuration注解, 设置Configuration_class属性为full * * proxyBeanMethods配置类是用来指定@Bean注解标注的方法是否使用代理, * 默认是true使用代理,直接从IOC容器之中取得对象; * 如果设置为false,也就是不使用注解,每次调用@Bean标注的方法获取到的对象和IOC容器中的都不一样,是一个新的对象,所以我们可以将此属性设置为false来提高性能。 */ if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) { beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL); } // 判断是不是带了@Component, @ComponentScan @Import @ImportResource @Bean注解, // 如果带有这几种注解, 就将其Configuration_class属性为lite类型的配置类 else if (config != null || isConfigurationCandidate(metadata)) { beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE); } else { return false; } // It's a full or lite configuration candidate... Let's determine the order value, if any. Integer order = getOrder(metadata); if (order != null) { beanDef.setAttribute(ORDER_ATTRIBUTE, order); } return true; }
上面主要是获取元数据, 然后判断元数据中是否有Configuration注解. 如果有,返回其属性. 我们判断其属性中proxyBeanMethods是否true, 如果是true, 那么将其设置为full.
如果配置中带有@Component, @ComponentScan @Import @ImportResource @Bean这几种属性之一, 那么就将其设置为lite.
问题5: cglib动态代理做了什么事情呢?
不看源码的情况下, 简单可以理解为, 去ioc工厂里面通过getBean("car") 查询了看ioc中是否有这个对象, 如果有就取出来, 不再另创建.
这也是@Configuration 和其他注解类似@Component和@ComponentScan的本质区别:
当在配置类中一个@Bean使用方法的方式引入另一个Bean的时候, 如果不加@Configuration注解, 就会重复创建Bean
如果加了@Configuration, 则会在这里创建一个cglib代理, 当调用了@Bean方法是会先检测容器中是否存在这个Bean, 如果不存在则创建, 存在则直接使用.
下面来看个例子
基础类: public class Car { private String name; private Tank tank; public String getName() { return name; } public void setName(String name) { this.name = name; } public Tank getTank() { return tank; } public void setTank(Tank tank) { this.tank = tank; } } public class Tank { private String name; public Tank() { System.out.println("创建一个tank"); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
这是定义的car和tank的基础类
@Configuration @ComponentScan(basePackages = {"com.lxl.www.iocbeanlifecicle"}) public class MainConfig { @Bean("car") public Car car() { Car car = new Car(); car.setName("zhangsan"); // 这里调用了Tank类, tank是通过@Bean注解注入的. car.setTank(tank()); return car; } @Bean public Tank tank() { return new Tank(); } }
当配置类使用了@Configuration注解的时候, 运行main方法
public class MainStarter { public static void main(String[] args) { // 第一步: 通过AnnotationConfigApplicationContext读取一个配置类 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class); context.scan("package"); //context.addBeanFactoryPostProcessor(); Car car = (Car) context.getBean("car"); Car car2 = (Car) context.getBean("car"); System.out.println(car.getName()); context.close(); } }
当去掉@Configuration注解的时候, 再次运行, 我们看到创建了两次tank
//@Configuration @ComponentScan(basePackages = {"com.lxl.www.iocbeanlifecicle"}) public class MainConfig { @Bean("car") public Car car() { Car car = new Car(); car.setName("zhangsan"); // 这里调用了Tank类, tank是通过@Bean注解注入的. car.setTank(tank()); return car; } @Bean public Tank tank() { return new Tank(); } }
在main方法中调用了两次(Car) context.getBean("car");
在new一个对象的时候, 如果不取ioc容器中取, 那么每一次都会创建一个新的.
在ioc容器中, car对象只有一个, 但是在构建car的时候, 调用了tank, tank在ioc容器中却不一定只有一份. 只有使用了@Configuration, 表示需要使用cglib动态代理查找tank类, 保证ioc容器中只有一份.
7. 详细研究四次调用中的第一次调用. 通过分析跟踪@ComponentScan注解是如何解析的,
通过跟踪@ComponentScan注解是如何解析的, 分来理解BeanDefinitionScan, BeanDefinitionRegistry, BeanDefinitionReader是如何工作的.
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { /** * 首先,调用BeanDefinitionRegistryPostProcessors 的后置处理器 * 定义已处理的后置处理器 */ // Invoke BeanDefinitionRegistryPostProcessors first, if any. Set<String> processedBeans = new HashSet<>(); /** * 这里一共分为两大步: * 第一步: 调用所有实现了 BeanDefinitionRegistryPostProcessor 接口的bean定义. (BeanDefinitionRegistryPostProcessor带注册功能的后置处理器) * 第二步: 调用BeanFactoryPostProcessor Bean工厂的后置处理器 */ /**********************第一步: 调用所有实现了BeanDefinitionRegistryPostProcessor接口的bean定义 begin****************************/ // 判断beanFactory是否实现了BeanDefinitionRegistry, 实现了该结构就有注册和获取Bean定义的能力 if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); } } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! // Separate between BeanDefinitionRegistryPostProcessors that implement // PriorityOrdered, Ordered, and the rest. /** * 这是一个集合, 存马上即将要被调用的BeanDefinitionRegistryPostProcessor */ List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); // 首先, 调用实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors // 在所有创世纪的后置处理器中, 只有 internalConfigurationAnnotationProcessor 实现了 BeanDefinitionRegistryPostProcessors 和 PriorityOrdered // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { // 判断beanFactory是否实现了PriorityOrdered接口. 如果实现了,是最优先调用. // 在整个加载过程中,会调用四次BeanDefinitionRegistryPostProcessor, 而实现了PriorityOrdered的接口最先调用 if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { // 调用beanFactory.getBean实例化配置类的后置处理器(创世界的类ppName), 也就是初始化, 实例化, 赋值属性. currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); /** * 第一次调用BeanDefinitionRegistryPostProcessors * 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor * 用于进行bean定义的加载 比如我们的包扫描 @import 等 */ invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); // 处理完了,清空currentRegistryProcessors currentRegistryProcessors.clear();
这里也有两大步
第一步: 初始化bean工厂的后置处理器
通过调用beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class) 初始化了bean工厂的后置处理器,
第二步: 解析配置
调用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);调用beanDefinitionRegistry的后置处理器. 筛选出符合条件的配置类.
如上图所示, 最后筛选出的配置类只有MainConfig配置类. 也就是说configCandidates配置候选集合中只有一个MainConfig
// 创建一个ConfigurationClassParser对象, 解析@Configuration class ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size()); do { // 执行解析 parser.parse(candidates); parser.validate();
然后, 接下来创建了一个对象ConfigurationClassParser, 这是一个配置类解析器. 下面将使用这个解析器解析配置类.
重点是如何解析的, 代码已重点标注出来了.
// 执行解析 parser.parse(candidates);
我们这里是通过注解解析的, 所以直接看下面的代码
public void parse(Set<BeanDefinitionHolder> configCandidates) { // 循环配置类 for (BeanDefinitionHolder holder : configCandidates) { BeanDefinition bd = holder.getBeanDefinition(); try { // 真正的解析bean定义:通过注解元数据解析 if (bd instanceof AnnotatedBeanDefinition) { parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName()); } ...... }
解析主要做了几件事呢?如下图:
解析配置类, 看看配置类是否含有如上标记的注解, 如果有, 则调用响应的返回对其进行解析,处理.
下面来看看源码. 是如何处理这一块的.
/** * 在这里会解析@Component @PropertySources @ComponentScan @ImportResource * @param configClass * @param sourceClass * @param filter * @return * @throws IOException */ @Nullable protected final SourceClass doProcessConfigurationClass( ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException { // 1. 处理@Component注解,判断元数据是否带有Component注解 if (configClass.getMetadata().isAnnotated(Component.class.getName())) { // Recursively process any member (nested) classes first processMemberClasses(configClass, sourceClass, filter); } // Process any @PropertySource annotations // 2. 处理@PropertySource 注解, 判断元数据是否带有@PropertySource注解 for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) { if (this.environment instanceof ConfigurableEnvironment) { processPropertySource(propertySource); } else { logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment"); } } // Process any @ComponentScan annotations // 3. 处理@ComponentScan注解, 判断元数据是否带有@ComponentScan注解 /** * 这里mainConfig配置类中有两个注解,一个是@Configuration ,一个是@ComponentScan. 在这里, 我们看一下@ComponentScan */ //componentScans 拿到的就是ComponentScan注解里的属性 Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { for (AnnotationAttributes componentScan : componentScans) { // The config class is annotated with @ComponentScan -> perform the scan immediately // 解析扫描出来的类, 将其解析为BeanDefinitionHolder对象, 并放入到scannedBeanDefinitions中 // 这正的解析ComponentScans和ComponentScan中的配置 Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); // 循环处理包扫描出来的bean定义 // Check the set of scanned definitions for any further config classes and parse recursively if needed for (BeanDefinitionHolder holder : scannedBeanDefinitions) { BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); if (bdCand == null) { bdCand = holder.getBeanDefinition(); } // 判断当前扫描出来的是不是一个配置类, 如果是的话, 直接进行递归解析. if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } } // 4. 处理@Import注解 // Process any @Import annotations processImports(configClass, sourceClass, getImports(sourceClass), filter, true); // 5. 处理@ImportResource注解 // Process any @ImportResource annotations AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); if (importResource != null) { String[] resources = importResource.getStringArray("locations"); Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader"); for (String resource : resources) { String resolvedResource = this.environment.resolveRequiredPlaceholders(resource); configClass.addImportedResource(resolvedResource, readerClass); } } // 6. 处理@Bean注解 // Process individual @Bean methods Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); } // 处理默认方法 // Process default methods on interfaces processInterfaces(configClass, sourceClass); // 处理超类 // Process superclass, if any if (sourceClass.getMetadata().hasSuperClass()) { String superclass = sourceClass.getMetadata().getSuperClassName(); if (superclass != null && !superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) { this.knownSuperclasses.put(superclass, configClass); // Superclass found, return its annotation metadata and recurse return sourceClass.getSuperClass(); } } // No superclass -> processing is complete return null; }
下面我们重点看对@ComponentScan和@ComponentScans注解的解析, 为什么看他呢? 因为很多注解都标记了@Component注解.
比如@Service注解,本身使用@Component
再来看@Controller注解, 其实质也是一个@Component注解
我们在自定义配置类的时候, 会使用@ComponentScan注解. 并传递一个包, 作为扫描包. 如MainConfig配置
这就会扫描包下所有的配置类.
它主要的逻辑如下:
在拿到@ComponentScan注解以后, 会对其进行parse. 主要解析里面的注解. 并对每一个注解进行处理. 处理后将其添加到scanner属性中. 最后调用scanner.doScan(....)方法.
源码如下:
// 解析配置 public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) { // 定义了一个类路径扫描器ClassPathBeanDefinitionScanner // 这里的scanner用于读取配置类 ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader); // 1. 判断是否有nameGenerator注解 // 为扫描器设置beanName的生成器对象, 并赋值给scanner, BeanNameGenerator的作用是为bean definitions生成Bean名字的接口 Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator"); boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass); scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator : BeanUtils.instantiateClass(generatorClass)); // 2. 判断是否有scopedProxy注解 ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy"); if (scopedProxyMode != ScopedProxyMode.DEFAULT) { scanner.setScopedProxyMode(scopedProxyMode); } else { Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver"); scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass)); } scanner.setResourcePattern(componentScan.getString("resourcePattern")); // 3. 判断属性中是否有includeFilters属性, 有的话就添加到scanner中 // 设置componentScan中包含的过滤器 -- 在使用注解的时候配置了包含和排除的过滤器, 这里进行处理 for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) { for (TypeFilter typeFilter : typeFiltersFor(filter)) { scanner.addIncludeFilter(typeFilter); } } // 4. 判断属性总是否有excludeFilters属性, 有的话放到scnanner中 // 设置componentScan中排除的过滤器 for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) { for (TypeFilter typeFilter : typeFiltersFor(filter)) { scanner.addExcludeFilter(typeFilter); } } // 5. 判断是否有lazyInit属性 // 获取配置类中懒加载初始化的属性 boolean lazyInit = componentScan.getBoolean("lazyInit"); if (lazyInit) { scanner.getBeanDefinitionDefaults().setLazyInit(true); } Set<String> basePackages = new LinkedHashSet<>(); // 6. 判断是否有basePackages属性 // 获取basePackages属性, 也就是我们定义的包扫描路径 String[] basePackagesArray = componentScan.getStringArray("basePackages"); for (String pkg : basePackagesArray) { String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg), ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); Collections.addAll(basePackages, tokenized); } for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) { basePackages.add(ClassUtils.getPackageName(clazz)); } if (basePackages.isEmpty()) { basePackages.add(ClassUtils.getPackageName(declaringClass)); } scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) { @Override protected boolean matchClassName(String className) { return declaringClass.equals(className); } }); // 调用scanner.doScan()方法, 扫描basePackages包 return scanner.doScan(StringUtils.toStringArray(basePackages)); }
调用doScan方法扫描配置类. 我们来看看主要做了哪些事情
第一步: 找到所有候选的BeanDefinition.
上面解析出了@ComponentScan注解传递过来的basePackages包. 扫描包中所有的类, 得到候选类.
扫描的时候做了几件事呢? 看最上图最右侧部分. 这扫描出来就是我们的目标类.
第二步: 解析这些准目标类.
第三步: 设置默认的beanDefinition属性
/** * 设置默认的bean定义的信息 * Apply the provided default values to this bean. * @param defaults the default settings to apply * @since 2.5 */ public void applyDefaults(BeanDefinitionDefaults defaults) { // 设置这个类是不是懒加载的 Boolean lazyInit = defaults.getLazyInit(); if (lazyInit != null) { setLazyInit(lazyInit); } // 设置默认的自动装配方式 setAutowireMode(defaults.getAutowireMode()); setDependencyCheck(defaults.getDependencyCheck()); // 设置初始化方法的名称 setInitMethodName(defaults.getInitMethodName()); // 是否可以调用InitMethod方法 setEnforceInitMethod(false); setDestroyMethodName(defaults.getDestroyMethodName()); // 是否可以调用DestroyMethod方法 setEnforceDestroyMethod(false); }
第四步: 将解析出来的bean定义注册到ioc容器中
这里就调用了BeanDefinitionReaderUtils.registerBeanDefinition注册bean定义. 之前注册过配置类, 这里和其是一样的. 所以不再赘述了
这里有两个细节:
1. excludeFilter中排除了自己
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) { // 定义了一个类路径扫描器ClassPathBeanDefinitionScanner // 这里的scanner用于读取配置类 ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader); // 1. 判断是否有nameGenerator注解 // 为扫描器设置beanName的生成器对象 Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator"); boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass); scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator : BeanUtils.instantiateClass(generatorClass)); // 2. 判断是否有scopedProxy注解 ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy"); if (scopedProxyMode != ScopedProxyMode.DEFAULT) { scanner.setScopedProxyMode(scopedProxyMode); } else { Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver"); scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass)); } scanner.setResourcePattern(componentScan.getString("resourcePattern")); // 3. 判断属性中是否有includeFilters属性, 有的话就添加到scanner中 // 设置componentScan中包含的过滤器 -- 在使用注解的时候配置了包含和排除的过滤器, 这里进行处理 for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) { for (TypeFilter typeFilter : typeFiltersFor(filter)) { scanner.addIncludeFilter(typeFilter); } } // 4. 判断属性总是否有excludeFilters属性, 有的话放到scnanner中 // 设置componentScan中排除的过滤器 for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) { for (TypeFilter typeFilter : typeFiltersFor(filter)) { scanner.addExcludeFilter(typeFilter); } } // 5. 判断是否有lazyInit属性 // 获取配置类中懒加载初始化的属性 boolean lazyInit = componentScan.getBoolean("lazyInit"); if (lazyInit) { scanner.getBeanDefinitionDefaults().setLazyInit(true); } Set<String> basePackages = new LinkedHashSet<>(); // 6. 判断是否有basePackages属性 // 获取basePackages属性, 也就是我们定义的包扫描路径 String[] basePackagesArray = componentScan.getStringArray("basePackages"); for (String pkg : basePackagesArray) { String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg), ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); Collections.addAll(basePackages, tokenized); } for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) { basePackages.add(ClassUtils.getPackageName(clazz)); } if (basePackages.isEmpty()) { basePackages.add(ClassUtils.getPackageName(declaringClass)); } // 想ExcludeFilter中添加默认的排除类, scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) { @Override protected boolean matchClassName(String className) { /** * declaringClass就是配置类MainConfig, 也就是说. 如果当前类是配置类, 那么就会排除掉 * 这是一个钩子方法, 现在不会调用. 后面才调用 * 在哪里调用呢? */ return declaringClass.equals(className); } }); // 调用scanner.doScan()方法, 扫描basePackages包 return scanner.doScan(StringUtils.toStringArray(basePackages)); }
在解析配置类的时候, 除了@ComponentScan注解中定义的ExcludeFilter和IncludeFilter以外, 还有默认的排除类. 如上加粗字体的部分. 这里是排除了配置类本身, 我们这里的配置类是MainConfig, 也就说, 会排除掉自己.
@Override protected boolean matchClassName(String className) { /** * declaringClass就是配置类MainConfig, 也就是说. 如果当前类是配置类, 那么就会排除掉 * 这是一个钩子方法, 现在不会调用. 后面才调用 * 在哪里调用呢? 先记住这个钩子方法matchClassName */ return declaringClass.equals(className); }
matchClassName是一个钩子方法. 在执行到这里的时候, 不会真的去执行. 什么时候执行呢? 后面调用doScan的时候执行.
protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>(); // 循环包路径 for (String basePackage : basePackages) { // 第一步: 找到所有候选的BeanDefinition /** * 在候选的配置类中, 排除掉了自己, 同时包含了默认的配置类 */ Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
在寻找候选配置类的时候, 进行了排除了配置类本身.
public Set<BeanDefinition> findCandidateComponents(String basePackage) { if (this.componentsIndex != null && indexSupportsIncludeFilters()) { return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); } else { // 扫描basePackages, 获取候选类 return scanCandidateComponents(basePackage); } }
进入这个方法
private Set<BeanDefinition> scanCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<>(); try { //第一步: 将com.lxl.www.iocbeanlifecicle转换成了物理路径com/lxl/www/iocbeanlifecicle String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; //第二步: .getResources(...)读取到了包下所有的类 Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } //第三步: 判断这个类是否是可读的? if (resource.isReadable()) { try { MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); //第四步: 判断这个类是否是我们要排除的 或者 包含的 if (isCandidateComponent(metadataReader)) { // 通过scnner扫描出来的beanDefinition是ScannedGenericBeanDefinition类型 ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); // 设置sbd的原类路径 sbd.setSource(resource);
在第四步的时候调用了isCandidateComponent(metadataReader, 这里就判断了是否是包含的类,或者是排除的类
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { // 判断这个类类是否是我们设置的要排除的? // 这里依然使用到了策略设计模式. TypeFilter是一个父类, 不同子类的TypeFilter会调用不同的match方法 for (TypeFilter tf : this.excludeFilters) { // 在这里面排除类配置类本身 if (tf.match(metadataReader, getMetadataReaderFactory())) { return false; } } // 判断这个类是否是我们要包含的? for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return isConditionMatch(metadataReader); } } return false; }
紫色加错的部分是就是判读是否符合排除的类. 红色加错的部分是判断是否是包含的类.
先来看紫色的部分, 排除的类
@Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { // This method optimizes avoiding unnecessary creation of ClassReaders // as well as visiting over those readers. if (matchSelf(metadataReader)) { return true; } ClassMetadata metadata = metadataReader.getClassMetadata(); // 排除配置类. if (matchClassName(metadata.getClassName())) { return true; }
看到了么, 这里调用了matchClassName. 这就是上面定义的钩子方法,
@Override protected boolean matchClassName(String className) { /** * declaringClass就是配置类MainConfig, 也就是说. 如果当前类是配置类, 那么就会排除掉 * 这是一个钩子方法, 现在不会调用. 后面才调用 * 在哪里调用呢? 先记住这个钩子方法matchClassName */ return declaringClass.equals(className); }
此时declaringClass表示的是当前的配置类, className表示的是目标类, 如果当前目标类 == 配置类, 那么就放回true. 返回true, 则会排除掉
2. includeFilter中包含了默认的配置类
下面来看红色加错的部分
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { // 判断这个类类是否是我们设置的要排除的? // 这里依然使用到了策略设计模式. TypeFilter是一个父类, 不同子类的TypeFilter会调用不同的match方法 for (TypeFilter tf : this.excludeFilters) { // 在这里面排除类配置类本身 if (tf.match(metadataReader, getMetadataReaderFactory())) { return false; } } // 判断这个类是否是我们要包含的? for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return isConditionMatch(metadataReader); } } return false; }
我们看到这里有this.includeFilters.包含的过滤器. 这里面是有值的
我们没有在配置类MainConfig上设置includeFilter啊, 这里面怎么会有值呢?
这是因为我们有默认包含的过滤器, 下面看看默认包含的过滤器是在哪里设置的.
首先从入口类点击AnnotationConfigApplicationContext
然后在点击this();
再点击ClassPathBeanDefinitionScanner
然后一路点击三个this(...)
最后看到上图 registerDefaultFilter();注册默认的过滤器
@SuppressWarnings("unchecked") protected void registerDefaultFilters() { // 注册默认的filter---第一个: 在includeFilter中增加了Component this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try { // 注册默认的filter---第二个:在includeFilter中增加了 javax.annotation.ManagedBean this.includeFilters.add(new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false)); logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip. } try { // 注册默认的filter---第三个:在includeFilter中增加了 javax.inject.Named this.includeFilters.add(new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false)); logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip. } }
如上图看到, 注册了3个默认的过滤器. 分别是Component, ManagedBean, Named. 他们都是注解类型的过滤器AnnotationTypeFilter
其中javax.annotation.ManagedBean和javax.inject.Named是jdk提供给我们的.