本文涉及主题
1. beanfactoryPostProcessor调用过程源码剖析
2. 配置类的解析过程源码
3. 配置类@Configuration加与不加的区别
4. 重复beanName的覆盖规则
5. @ComponentScan的解析原理
一. 研究目标: 解析spring如何加载配置类
我们经常会在一个类上打上@Configuration,@Component,@Bean等. 带有这些注解的类,就是我们所说的配置类. 那么,spring启动的时候,是如何加载这些配置类的呢?
下面就以此为目的,分析spring源码. 本节的内容是对上一节内容的实战分析,同时更加详细的解读spring源码
我们知道,spring启动的时候做了3件事,就是上面的三件事.
第一件事: 调用this()自身的无参构造函数. 初始化了BeanDeFinitionReader和BeanDeFinitionScanner,同时初始化了很多spring的原始后置处理器,这些处理器是用来加载bean的
第二件事: 调用register(..) 注册配置类
第三件事: refresh(..) 这里包含了整个ioc创建bean的全生命周期, 今天重点看invokebeanfactoryPostProcessors(beanfactory)加载配置类
二. 准备工作: 自定义配置类MainConfig
我们先定义好要分析加载的配置类
package com.lxl.www.iocbeanlifecicle; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; /** * 这是一个配置类,* 在配置类里面定义了扫描的包路径com.lxl.www.iocbeanlifecicle * 这是会将这个包下配置了注解的类扫描到ioc容器里面,成为一个成熟的bean */ @Configuration @ComponentScan(basePackages = {"com.lxl.www.iocbeanlifecicle"}) public class MainConfig { }
这个配置类很简单,使用@ComponentScan注解指定了扫描的包. @Configuration指定当前是一个配置类
接下来定义一个main方法,加载配置类.
package com.lxl.www.iocbeanlifecicle; import org.springframework.context.annotation.AnnotationConfigApplicationContext; MainStarter { static void main(String[] args) { // 第一步: 通过AnnotationConfigApplicationContext读取一个配置类 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.); context.addbeanfactoryPostProcessor(); Car car = (Car) context.getBean(car"); System.out.println(car.getName()); context.close(); } }
在main里,通过AnnotationConfigurationApplicationContext读取配置类MainConfig.class.
配置类被传进来以后,到底是怎么被解析的呢? 这就是我们分析的线索
始终不要忘记我们的整体架构图. 对照这个图来分析. 思路更清晰. 整体内容讲解在这里: https://www.cnblogs.com/ITPower/p/13677635.html
下面,从入口进入. 我们的入口就是这里
下面进入AnnotationConfigApplicationContext的构造方法
public AnnotationConfigApplicationContext(Class<?>... componentClasses) { 进入构造函数,首先调用自身的构造方法this(); 调用自身的构造方法之前,要先调用父类的构造方法 this(); register配置注册类 register(componentClasses); ioc容器shua新接口--非常重要 refresh(); }
三、读取配置类后置处理器ConfigurationClasspostProcessor
3.1 调用this()无参构造函数
public AnnotationConfigApplicationContext() { * * 创建了一个Bean定义的读取器. * 完成了spring内部BeanDeFinition的注册(主要是后置处理器) * 读取了很多spring自定义的配置(主要是后置处理器). 这些类都是spring 的原始类(也就是创世纪的类). */ this.reader = new AnnotatedBeanDeFinitionReader(); * * 创建BeanDeFinition扫描器 * 可以用来扫描包或者类,进而转换为bd * * Spring默认的扫描包不是这个scanner对象 * 而是自己new的一个ClasspathBeanDeFinitionScanner * Spring在执行工程后置处理器ConfigurationClasspostProcessor时,去扫描包时会new一个ClasspathBeanDeFinitionScanner * * 这里的scanner仅仅是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法 * 通过调用context.scan("package name");扫描处理配置类 * 扫描 */ this.scanner = new ClasspathBeanDeFinitionScanner(this); }
在初始化AnnotatedBeanDeFinitionReader(this);的时候,注册了很多后置处理器
* * Register all relevant annotation post processors in the given registry. * @param registry the registry to operate on * @param source the configuration source element (already extracted) * that this registration was triggered from. May be {@code null}. * @return a Set of BeanDeFinitionHolders,containing all bean deFinitions * that have actually been registered by this call */ static Set<BeanDeFinitionHolder> registerannotationConfigProcessors( BeanDeFinitionRegistry registry,@Nullable Object source) { 获取到beanfactory DefaultListablebeanfactory beanfactory = unwrapDefaultListablebeanfactory(registry); * * 判断beanfactory中是否有AnnotationAwareOrderComparator和ContextAnnotationAutowireCandidateResolver * 没有则添加 if (beanfactory != null) { if (!(beanfactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { beanfactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } if (!(beanfactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { beanfactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); } } BeanDeFinitionHolder: 为BeanDeFinition设置名字和别名 Set<BeanDeFinitionHolder> beanDefs = new LinkedHashSet<>(8); 如果registry中没有ConfigurationClasspostProcessor配置类后置处理器,就添加一个 if (!registry.containsBeanDeFinition(CONfigURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDeFinition def = new RootBeanDeFinition(ConfigurationClasspostProcessor.class); def.setSource(source); 构建BeanDeFinitionHolder,并添加到beanDefs beanDefs.add(registerPostProcessor(registry,def,CONfigURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } 如果rigistry中,没有AutowiredAnnotationBeanPostProcessor Autowired注解bean的后置处理器,则添加一个 registry.containsBeanDeFinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDeFinition def = new RootBeanDeFinition(AutowiredAnnotationBeanPostProcessor.class); def.setSource(source); Check for JSR-250 support,and if present add the CommonAnnotationBeanPostProcessor. 检查对JSR-250的支持,如果rigistry中没有 CommonAnnotationBeanPostProcessor 通用注解后置处理器,1)">if (jsr250Present && !registry.containsBeanDeFinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDeFinition def = new RootBeanDeFinition(CommonAnnotationBeanPostProcessor. Check for JPA support,and if present add the PersistenceAnnotationBeanPostProcessor. 检查对jpa的支持,如果不包含 internalPersistenceAnnotationProcessor,持久化注解处理器,就添加一个 if (jpaPresent && !registry.containsBeanDeFinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDeFinition def = RootBeanDeFinition(); try { def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,AnnotationConfigUtils..getClassLoader())); } catch (ClassNotFoundException ex) { throw IllegalStateException( Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,ex); } def.setSource(source); beanDefs.add(registerPostProcessor(registry,PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)); } 检查对事件监听的支持,如果不包含事件监听处理器 internalEventListenerProcessor,1)">registry.containsBeanDeFinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) { RootBeanDeFinition def = new RootBeanDeFinition(EventListenerMethodProcessor.); def.setSource(source); beanDefs.add(registerPostProcessor(registry,EVENT_LISTENER_PROCESSOR_BEAN_NAME)); } 如果不包含事件监听工厂处理器 internalEventListenerFactory,1)">registry.containsBeanDeFinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) { RootBeanDeFinition def = new RootBeanDeFinition(DefaultEventListenerFactory.return beanDefs; }
我们看到,注册了6个原始RootBeanDeFinition,这些bean是spring自己提前定义好的,他们的加载是整个spring的基础. 用于解析spring中其他的类
而这一次我们要研究配置类是如何被读取的,所以重点关注的是下面这个后置处理器
这里还有很多其他的原始类被注册了,但我们的目标是分析配置类是如何被读取的,所以,其他的先忽略,只看ConfigurationClasspostProcessor.
3.2 ConfigurationClasspostProcessor的继承结构
可以看到ConfigurationClasspostProcessor是同时实现了BeanDeFinitionRegistryPostProcessor和beanfactoryPostProcessor. 这一点我们需要记住,后面会使用到
2.3 ConfigurationClasspostProcessor是如何被注册的
添加一个 registry.containsBeanDeFinition(CONfigURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDeFinition def = new RootBeanDeFinition(ConfigurationClasspostProcessor.); def.setSource(source); beanDefs.add(registerPostProcessor(registry,CONfigURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); }
首先,构建了一个RootBeanDeFinition. 然后调用了registerPostProcessor方法,三个入参分别是
registry: BeanDeFinitionRegistry注册器,用于注册BeanDeFinition
def: 刚刚构建的RootBeanDeFinition
CONfigURATION_ANNOTATION_PROCESSOR_BEAN_NAME: 构建BeanDeFinition使用的beanName是org.springframework.context.annotation.internalConfigurationAnnotationProcessor
然后调用registerPostProcessor方法
@Override registerBeanDeFinition(String beanName,BeanDeFinition beanDeFinition) throws BeanDeFinitionStoreException { Assert.hasText(beanName,Bean name must not be empty); Assert.notNull(beanDeFinition,1)">BeanDeFinition must not be null); if (beanDeFinition instanceof AbstractBeanDeFinition) { { ((AbstractBeanDeFinition) beanDeFinition).validate(); } (BeanDeFinitionValidationException ex) { BeanDeFinitionStoreException(beanDeFinition.getResourceDescription(),beanName,1)">Validation of bean deFinition Failed,ex); } } 从BeanDeFinition的一级缓存BeanDeFinitionMap中读取BeanDeFinition对象,判断是否已经存在 BeanDeFinition existingDeFinition = this.beanDeFinitionMap.get(beanName); // 这里,如果已经存在,说明被重复加载了,那么后面加载的会覆盖前面加载的bean if (existingDeFinition != 判断是否允许BeanDeFinition重写 isAllowBeanDeFinitionOverriding()) { BeanDeFinitionOverrideException(beanName,beanDeFinition,existingDeFinition); } else if (existingDeFinition.getRole() < beanDeFinition.getRole()) { e.g. was ROLE_APPLICATION,Now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE (logger.isInfoEnabled()) { logger.info(Overriding user-defined bean deFinition for bean '" + beanName + ' with a framework-generated bean deFinition: replacing [ existingDeFinition + ] with [" + beanDeFinition + ]); } } beanDeFinition.equals(existingDeFinition)) { (logger.isDebugEnabled()) { logger.debug(Overriding bean deFinition for bean '' with a different deFinition: replacing [" + existingDeFinition + else { (logger.isTraceEnabled()) { logger.trace(' with an equivalent deFinition: replacing [); } } // 覆盖一级缓存的bean定义 this.beanDeFinitionMap.put(beanName,beanDeFinition); } { 处理循环引用的问题 (hasBeanCreationStarted()) { Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (.beanDeFinitionMap) { .beanDeFinitionMap.put(beanName,beanDeFinition); List<String> updatedDeFinitions = new ArrayList<>(this.beanDeFinitionNames.size() + 1); updatedDeFinitions.addAll(.beanDeFinitionNames); updatedDeFinitions.add(beanName); this.beanDeFinitionNames = updatedDeFinitions; removeManualSingletonName(beanName); } } Still in startup registration phase Finition); .beanDeFinitionNames.add(beanName); removeManualSingletonName(beanName); } this.frozenBeanDeFinitionNames = ; } null || containsSingleton(beanName)) { resetBeanDeFinition(beanName); } (isConfigurationFrozen()) { clearByTypeCache(); } }
这里面的关键代码是标红的部分,将ConfigurationClasspostProcessor放入到了beanDeFinitionMap里面
下面的else是处理循环引用的问题,暂时先不要看.
3.3 对照整体框架,我们知道ConfigurationClasspostProcessor被解析成beanDeFinition放入到BeanDeFinitionMap中了
3.4 初始化ClasspathBeanDeFinitionScanner
在this()构造方法里,还初始化了ClasspathBeanDeFinitionScanner,这里只说一句.
this);
我们在扫描配置类的时候,确实使用的是ClasspathBeanDeFinitionScanner,但是,不是this.scanner对象. 而是自己new的一个ClasspathBeanDeFinitionScanner.
这里的scanner仅仅是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法
通过调用context.scan("package name");扫描处理配置类
使用方式如下:
第一步: 通过AnnotationConfigApplicationContext读取一个配置类 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.); context.scan("package"); Car car = (Car) context.getBean(.println(car.getName()); context.close(); }
到目前为止完成了后置处理器注册为BeanDeFinition
备注:
ConfigurationClasspostProcessor是一个工具类,这个类的作用是解析配置类.
工具类有了,那么还得有主角呀,那就是我们上面的配置类. 下面看看配置类的加载
四. 读取自定义配置类MainConfig
注册配置类,入口自然是这里了
(); // register配置注册类 register(componentClasses); refresh(); }
跟踪进去找到doRegisterBean(...)方法
private <T> void doRegisterBean(Class<T> beanClass,@Nullable String name,@Nullable Class<? extends Annotation>[] qualifiers,@Nullable supplier<T> supplier,@Nullable BeanDeFinitionCustomizer[] customizers) { 将入参的配置类beanClass构建成AnnotatedGenericBeanDeFinition对象 AnnotatedGenericBeanDeFinition abd = AnnotatedGenericBeanDeFinition(beanClass); if (.conditionEvaluator.shouldSkip(abd.getMetadata())) { ; } abd.setInstancesupplier(supplier); 读取配置类的元数据 ScopeMetadata scopeMetadata = .scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd,.registry)); 处理主类通用定义注解 AnnotationConfigUtils.processCommonDeFinitionAnnotations(abd); if (qualifiers != for (Class<? extends Annotation> qualifier : qualifiers) { if (Primary.class == qualifier) { abd.setPrimary(true); } if (Lazy. qualifier) { abd.setLazyInit( { abd.addQualifier( AutowireCandidateQualifier(qualifier)); } } } if (customizers != for (BeanDeFinitionCustomizer customizer : customizers) { customizer.customize(abd); } } 将MainConfig.java配置类进行解析.放到BeanDeFinitionHolder BeanDeFinitionHolder deFinitionHolder = BeanDeFinitionHolder(abd,beanName); deFinitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata,deFinitionHolder,1)">.registry); BeanDeFinitionReaderUtils.registerBeanDeFinition(deFinitionHolder,this.registry); }
重点就是红色这句话,其他可以略过,因为我们的配置类很简单,直接看BeanDeFinitionReaderUtils.registerBeanDeFinition(deFinitionHolder, this.registry);
我们找到 registry.registerBeanDeFinition(beanName,deFinitionHolder.getBeanDeFinition());方法,进入到DefaultListablebeanfactory查看方法,这个方法之前我们已经调用过一次
就是在注册ConfigurationClasspostProcessor的时候,我们需要将其解析为BeanDeFinition然后放到BeanDeFinitionMap中,这里也是一样的,将我们的配置类MainConfig解析成BeanDeFinition放入到BeanDeFinitionMap中.
这里的代码在整个框架中处于什么位置呢? 将MainConfig解析为BeanDeFinition放入到BeanDeFinitionMap中
以上两步,一个是将ConfigurationClasspostProcessor配置类后置处理器,也就是解析配置的工具类,解析成BeanDeFinition放入到BeanDeFinitionMap中
另一个是将我们的目标配置类MainConfig加载到内存,组装成BeanDeFinition放入到BeanDeFinitionMap中.
到这里,我们完成了两步.
第一步: 准备工具类ConfigurationClasspostProcessor
第二步: 准备配置类MainConfig.
接下俩,就是要使用工具类来解析配置类MainConfig了
五. 调用bean工厂的后置处理器invokebeanfactoryPostProcessors(beanfactory);
register(componentClasses); // ioc容器刷新接口--非常重要 refresh(); }
在refresh()中有很多步骤,我们重点来看invokebeanfactoryPostProcessors(beanfactory);
* * refresh是spring最核心的方法,里面包含了整个spring ioc的全过程,包括spring加载bean到销毁bean的全过程 * 学习spring,就是学习里面的13个方法,如果13个方法都学完了,基本上就打通了 * @throws BeansException * @throws IllegalStateException @Override refresh() throws BeansException,IllegalStateException { synchronized (.startupShutdownMonitor) { 1. 准备刷新上下文环境 prepareRefresh(); Tell the subclass to refresh the internal bean factory. 2. 获取告诉子类初始化bean工厂,不同工厂不同实现 ConfigurableListablebeanfactory beanfactory = obtainFreshbeanfactory(); Prepare the bean factory for use in this context. 3. 对bean工厂进行填充属性 preparebeanfactory(beanfactory); Allows post-processing of the bean factory in context subclasses. 4. 留个子类去实现该接口 postProcessbeanfactory(beanfactory); Invoke factory processors registered as beans in the context. * * 调用bean工厂的后置处理器 * 我们之前在Reader的时候读取了很多创世纪的PostProcessor后置处理器. * 这里要调用bean工厂的后置处理器. 这么多创世纪的PostProcessor,只有一个PostProcessor实现了 * beanfactoryPostProcessor. 那个类就是 ConfigurationClasspostProcessor * 前面已经将ConfigurationClasspostProcessor放入到BeanDeFinitionMap中了,* 对应的BeanDeFinitionName 是 internalConfigurationAnnotationProcessor * * * */ invokebeanfactoryPostProcessors(beanfactory); Register bean processors that intercept bean creation. 注册bean后置处理器 registerBeanPostProcessors(beanfactory); Initialize message source for this context. 初始化国际化资源处理器 initMessageSource(); Initialize event multicaster for this context. 创建事件多播放器 initApplicationEventMulticaster(); Initialize other special beans in specific context subclasses. 这个方法通用也是留个子类实现的,spring boot也是从这个方法进行启动 onRefresh(); Check for listener beans and register them. 将事件监听器注册到多播放器上 registerListeners(); Instantiate all remaining (non-lazy-init) singletons. 实例化剩余的单实例bean * * 这个方法就是循环遍历BeanDeFinitionMap,调用getBean,去生产bean finishbeanfactoryInitialization(beanfactory); Last step: publish corresponding event. 最后容器刷新 发布刷新时间(spring cloud是从这里启动的 ) finishRefresh(); } ........ }
invokebeanfactoryPostProcessors(beanfactory);看名字,调用的是Bean工厂的后置处理器,上面分析了,初始化的时候初始化了很多spring原生的后置处理器,这么多后置处理器,其实,只有一个后置处理器实现了beanfactoryPostProcessor,它就是ConfigurationClasspostProcessor,还记得上面的结构图么,拿下来,再看一遍.
这里调用的时候,原生处理器只会调用ConfigurationClasspostProcessor
protected invokebeanfactoryPostProcessors(ConfigurableListablebeanfactory beanfactory) { /** * 获取两处存储beanfactoryPostProcessor的对象,传入供接下来调用 * 1. 当前bean工厂 * 2. 和我们自己调用addBeanFacoryPostProcessor自定义beanfactoryPostProcessor * * 参数: getbeanfactoryPostProcessors() 传了一个工厂的后置处理器的List,这个时候list是空的 * getbeanfactoryPostProcessors()里面的值是怎么来的呢? * 通过在自定义main方法中调用context.addbeanfactoryPostProcessor(...);来添加 * * public static void main(String[] args) { * // 第一步: 通过AnnotationConfigApplicationContext读取一个配置类 * AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class); * context.addbeanfactoryPostProcessor(...); * Car car = (Car) context.getBean("car"); * System.out.println(car.getName()); * context.close(); * } */ PostProcessorRegistrationDelegate.invokebeanfactoryPostProcessors(beanfactory,getbeanfactoryPostProcessors()); Detect a LoadTimeweaver and prepare for weaving,if found in the meantime (e.g. through an @Bean method registered by ConfigurationClasspostProcessor) if (beanfactory.getTempClassLoader() == null && beanfactory.containsBean(LOAD_TIME_weaveR_BEAN_NAME)) { beanfactory.addBeanPostProcessor( LoadTimeweaverAwareProcessor(beanfactory)); beanfactory.setTempClassLoader( ContextTypeMatchClassLoader(beanfactory.getBeanClassLoader())); } ...... }
这里要调用bean工厂的后置处理器了. 看上面的注释,注释写的很清晰.
在调用PostProcessorRegistrationDelegate.invokebeanfactoryPostProcessors(beanfactory,getbeanfactoryPostProcessors());的时候调用了getbeanfactoryPostProcessors()方法.
public List<beanfactoryPostProcessor> getbeanfactoryPostProcessors() { return this.beanfactoryPostProcessors; }
getbeanfactoryPostProcessors() 返回的是一个工厂的后置处理器的List,这个时候list是空的 getbeanfactoryPostProcessors()里面的值是怎么来的呢? 通过在自定义main方法中调用context.addbeanfactoryPostProcessor(...);来添加. 也就是通过main方法手动添加的beanfactoryPostProcessor. 如下所示
main(String[] args) { 第一步: 通过AnnotationConfigApplicationContext读取一个配置类 AnnotationConfigApplicationContext context = ); context.addbeanfactoryPostProcessor(...); Car car = (Car) context.getBean(); System..println(car.getName()); context.close(); }
接下来重点来了. PostProcessorRegistrationDelegate.invokebeanfactoryPostProcessors(beanfactory,getbeanfactoryPostProcessors()); 方法实现一共分为两大步:
第一步: 调用所有实现了 BeanDeFinitionRegistryPostProcessor 接口的bean定义. (BeanDeFinitionRegistryPostProcessor带注册功能的后置处理器)
第二步: 调用beanfactoryPostProcessor Bean工厂的后置处理器
第一步: 调用所有实现了 BeanDeFinitionRegistryPostProcessor 接口的bean定义.
来看看源码是如何定义的. 重点看代码的注释,每一部分的功能都有明确标出,注释写的很详细
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定义的能力 (beanfactory instanceof BeanDeFinitionRegistry) { BeanDeFinitionRegistry registry = (BeanDeFinitionRegistry) beanfactory; List<beanfactoryPostProcessor> regularPostProcessors = new ArrayList<>(); List<BeanDeFinitionRegistryPostProcessor> registryProcessors = (); (beanfactoryPostProcessor postProcessor : beanfactoryPostProcessors) { (postProcessor instanceof BeanDeFinitionRegistryPostProcessor) { BeanDeFinitionRegistryPostProcessor registryProcessor = (BeanDeFinitionRegistryPostProcessor) postProcessor; registryProcessor.postProcessBeanDeFinitionRegistry(registry); registryProcessors.add(registryProcessor); } { 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 = (); // 第一步,调用实现了PriorityOrdered的BeanDeFinitionRegistryPostProcessors 在所有创世纪的后置处理器中,只有 internalConfigurationAnnotationProcessor 实现了 BeanDeFinitionRegistryPostProcessors 和 PriorityOrdered First,invoke the BeanDeFinitionRegistryPostProcessors that implement PriorityOrdered. String[] postProcessorNames = beanfactory.getBeanNamesForType(BeanDeFinitionRegistryPostProcessor.class,1)">true,1)">false); (String ppName : postProcessorNames) { 判断beanfactory是否实现了PriorityOrdered接口. 如果实现了,是最优先调用. 在整个加载过程中,会调用四次BeanDeFinitionRegistryPostProcessor,而实现了PriorityOrdered的接口最先调用 if (beanfactory.isTypeMatch(ppName,PriorityOrdered.)) { 调用beanfactory.getBean实例化创世界的类ppName currentRegistryProcessors.add(beanfactory.getBean(ppName,BeanDeFinitionRegistryPostProcessor.)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors,beanfactory); registryProcessors.addAll(currentRegistryProcessors); * * 第一次调用BeanDeFinitionRegistryPostProcessors * 在这里典型的BeanDeFinitionRegistryPostProcessors就是ConfigurationClasspostProcessor * 用于进行bean定义的加载 比如我们的包扫描 @import 等 invokeBeanDeFinitionRegistryPostProcessors(currentRegistryProcessors,registry); 处理完了,清空currentRegistryProcessors currentRegistryProcessors.clear(); // 第二步: 调用实现 Ordered 的 BeanDeFinitionRegistryPostProcessors。 Next,invoke the BeanDeFinitionRegistryPostProcessors that implement Ordered. postProcessorNames = beanfactory.getBeanNamesForType(BeanDeFinitionRegistryPostProcessor. 这时实现了PriorityOrdered.class的postProcessor就不会再被加载进来了,因为processedBeans.contains(ppName) == true if (!processedBeans.contains(ppName) && beanfactory.isTypeMatch(ppName,Ordered. 将其放入到currentRegistryProcessors,马上就要被调用 currentRegistryProcessors.add(beanfactory.getBean(ppName,1)">)); processedBeans.add(ppName); } } 对所有的处理器进行排序. 调用了Ordered的方法,会返回排序(一个数字),然后根据数字排序即可 sortPostProcessors(currentRegistryProcessors,beanfactory); registryProcessors.addAll(currentRegistryProcessors); * * 第二次调用BeanDeFinitionRegistryPostProcessors * 在这里典型的BeanDeFinitionRegistryPostProcessors就是ConfigurationClasspostProcessor * 用于进行bean定义的加载 比如我们的包扫描 @import 等 // 第三步. 调用没有实现任何优先级接口的 BeanDeFinitionRegistryPostProcessor Finally,invoke all other BeanDeFinitionRegistryPostProcessors until no further ones appear. boolean reiterate = ; while (reiterate) { reiterate = ; 获取 postProcessorNames = beanfactory.getBeanNamesForType(BeanDeFinitionRegistryPostProcessor.); (String ppName : postProcessorNames) { 已处理过的postProcessor不再处理 processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanfactory.getBean(ppName,BeanDeFinitionRegistryPostProcessor.)); processedBeans.add(ppName); reiterate = ; } } sortPostProcessors(currentRegistryProcessors,beanfactory); registryProcessors.addAll(currentRegistryProcessors); * * 第三次调用BeanDeFinitionRegistryPostProcessors * 在这里典型的BeanDeFinitionRegistryPostProcessors就是ConfigurationClasspostProcessor * 用于进行bean定义的加载 比如我们的包扫描 @import 等 invokeBeanDeFinitionRegistryPostProcessors(currentRegistryProcessors,registry); currentRegistryProcessors.clear(); } Now,invoke the postProcessbeanfactory callback of all processors handled so far. * 第四步:调用bean工厂的后置处理器 * registryProcessors: 带有注册功能的bean工厂的后置处理器 * regularPostProcessors: 不带注册功能的bean工厂的后置处理器 invokebeanfactoryPostProcessors(registryProcessors,beanfactory); invokebeanfactoryPostProcessors(regularPostProcessors,beanfactory); } * 如果当前的beanfactory没有实现BeanDeFinitionRegistry 说明没有注册Bean定义的能力 * 那么就直接调用 BeanDeFinitionRegistryPostProcessor.postProcessbeanfactory方法 */ Invoke factory processors registered with the context instance. invokebeanfactoryPostProcessors(beanfactoryPostProcessors,beanfactory); } *********************第一步: 调用所有实现了BeanDeFinitionRegistryPostProcessor接口的bean定义 end************************************************第二步: 调用beanfactoryPostProcessor Bean工厂的后置处理器 begin*************************** Do not initialize factorybeans here: We need to leave all regular beans uninitialized to let the bean factory post-processors apply to them! String[] postProcessorNames = beanfactory.getBeanNamesForType(beanfactoryPostProcessor. Separate between beanfactoryPostProcessors that implement PriorityOrdered, Ordered,and the rest. 优先排序的后置处理器 List<beanfactoryPostProcessor> priorityOrderedPostProcessors = (); List<String> orderedPostProcessorNames = (); List<String> nonorderedPostProcessorNames = (String ppName : postProcessorNames) { (processedBeans.contains(ppName)) { skip - already processed in first phase above } )) { priorityOrderedPostProcessors.add(beanfactory.getBean(ppName,beanfactoryPostProcessor.)); } )) { orderedPostProcessorNames.add(ppName); } { nonorderedPostProcessorNames.add(ppName); } } 首先,调用有优先级排序的后置处理器 beanfactoryPostProcessors that implement PriorityOrdered. sortPostProcessors(priorityOrderedPostProcessors,beanfactory); invokebeanfactoryPostProcessors(priorityOrderedPostProcessors,beanfactory); 第二,调用实现了Ordered排序的后置处理器 beanfactoryPostProcessors that implement Ordered. List<beanfactoryPostProcessor> orderedPostProcessors = (orderedPostProcessorNames.size()); (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanfactory.getBean(postProcessorName,1)">)); } sortPostProcessors(orderedPostProcessors,beanfactory); invokebeanfactoryPostProcessors(orderedPostProcessors,1)"> 最后,调用没有实现任何排序接口的beanfactory后置处理器 beanfactoryPostProcessors. List<beanfactoryPostProcessor> nonorderedPostProcessors = (nonorderedPostProcessorNames.size()); (String postProcessorName : nonorderedPostProcessorNames) { nonorderedPostProcessors.add(beanfactory.getBean(postProcessorName,1)">)); } invokebeanfactoryPostProcessors(nonorderedPostProcessors,1)">*********************第二步: 调用beanfactoryPostProcessor Bean工厂的后置处理器 end*************************** Clear cached merged bean deFinitions since the post-processors might have modified the original Metadata,e.g. replacing placeholders in values... beanfactory.clearMetadataCache(); }
下面我们就来分析上图所示的内容.
1. 对照源码和上图,我们来看第一次调用
// 第一次,调用实现了PriorityOrdered的BeanDeFinitionRegistryPostProcessors FinitionRegistryPostProcessors that implement PriorityOrdered. String[] postProcessorNames = beanfactory.getBeanNamesForType(BeanDeFinitionRegistryPostProcessor.class,true,false); PriorityOrdered.class)) { */ invokeBeanDeFinitionRegistryPostProcessors(currentRegistryProcessors,registry); FinitionRegistryPostProcessor的后置处理器,上面我们做过铺垫,只有ConfigurationClasspostProcessor实现了BeanDeFinitionRegistryPostProcessor后置处理器所以,这里过滤出来的postProcessorNames只有一个,就是ConfigurationClasspostProcessor,接下来,判断这个类是否实现了PriorityOrdered 优先排序的接口,如果实现了,那么放入到currentRegistryProcessors中,后面会进行调用.
接下来,执行invokeBeanDeFinitionRegistryPostProcessors
这是第一次调用BeanDeFinitionRegistryPostProcessors
2. 第二次调用BeanDeFinitionRegistryPostProcessors
// 第二步: 调用实现 Ordered 的 BeanDeFinitionRegistryPostProcessors。 调用的时候,依然是获取所有的实现了BeanDeFinitionRegistryPostProcessor接口的后置处理器,且这个处理器没有实现过PriorityOrdered也就是没有被上面调用过. 且实现了Ordered接口这一类添加到currentRegistryProcessors集合中,然后调用invokeBeanDeFinitionRegistryPostProcessors处理
这是第二次调用BeanDeFinitionRegistryPostProcessor
3. 第三次调用BeanDeFinitionRegistryPostProcessor
第三步. 调用没有实现任何优先级接口的 BeanDeFinitionRegistryPostProcessor 调用的是没有实现过任何排序接口的后置处理器. 并将其放入到currentRegistryProcessors,然后执行invokeBeanDeFinitionRegistryPostProcessors
4. 第四次调用
beanfactory 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,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 MybeanfactoryPostProcessor implements BeanDeFinitionRegistryPostProcessor { @Override postProcessBeanDeFinitionRegistry(BeanDeFinitionRegistry registry) throws BeansException { } @Override postProcessbeanfactory(ConfigurableListablebeanfactory beanfactory) throws BeansException { } } 因为MybeanfactoryPostProcessor是自定义的,没有实现任何PriorityOrdered 或者 Order,因此,会调用3,1)">4
二. 详细研究第四步, invokebeanfactoryPostProcessors(registryProcessors,beanfactory);的逻辑.
我们在这一步打个断点,然后跟着断点一步一步点击进去
这是registryProcessors里面只有一个后置处理器,就是ConfigurationClasspostProcessor.
然后进入到ConfigurationClasspostProcessor.postProcessbeanfactory(ConfigurableListablebeanfactory beanfactory)方法
postProcessbeanfactory(ConfigurableListablebeanfactory beanfactory) { int factoryId = System.identityHashCode(beanfactory); .factoriesPostProcessed.contains(factoryId)) { IllegalStateException( postProcessbeanfactory already called on this post-processor against beanfactory); } .factoriesPostProcessed.add(factoryId); .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( ImportAwareBeanPostProcessor(beanfactory)); }
这里先看enhanceConfigurationClasses(beanfactory);个方法
enhanceConfigurationClasses(ConfigurableListablebeanfactory beanfactory) { Map<String,AbstractBeanDeFinition> configBeanDefs = new LinkedHashMap<> (String beanName : beanfactory.getBeanDeFinitionNames()) { BeanDeFinition beanDef = beanfactory.getBeanDeFinition(beanName); Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONfigURATION_CLASS_ATTRIBUTE); MethodMetadata methodMetadata = (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; abd.hasBeanClass()) { { abd.resolveBeanClass(.beanClassLoader); } (Throwable ex) { 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,如果不存在则创建,存在则直接使用. */ (ConfigurationClassUtils.CONfigURATION_CLASS_FULL.equals(configClassAttr)) { (beanDef instanceof AbstractBeanDeFinition)) { new BeanDeFinitionStoreException(Cannot enhance @Configuration bean deFinition ' beanName + ' since it is not stored in an AbstractBeanDeFinition subclassif (logger.isInfoEnabled() && beanfactory.containsSingleton(beanName)) { logger.info(' 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); } } (configBeanDefs.isEmpty()) { nothing to enhance -> return immediately ; } ConfigurationClassEnhancer enhancer = 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,1)">.beanClassLoader); if (configClass != enhancedClass) { (logger.isTraceEnabled()) { logger.trace(String.format(Replacing bean deFinition '%s' existing class '%s' with enhanced class '%s'figClass.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的时候,就会重复加载Bean.如果加了@Configuration,存在则直接使用.
问题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 static boolean checkConfigurationClassCandidate( BeanDeFinition beanDef,MetadataReaderFactory MetadataReaderFactory) { String className = beanDef.getBeanClassName(); if (className == null || beanDef.getFactoryMethodName() != return ; } 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(); } 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. AopInfrastructureBean. EventListenerFactory..isAssignableFrom(beanClass)) { ; } Metadata = AnnotationMetadata.introspect(beanClass); } { MetadataReader MetadataReader = MetadataReaderFactory.getMetadataReader(className); Metadata = MetadataReader.getAnnotationMetadata(); } (IOException ex) { Could not find class file for introspecting configuration annotations: className,ex); } ; } } 判断元数据中是否包含Configuration注解 Map<String,Object> config = Metadata.getAnnotationAttributes(Configuration..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类型的配置类 isConfigurationCandidate(Metadata)) { beanDef.setAttribute(CONfigURATION_CLASS_ATTRIBUTE,CONfigURATION_CLASS_LITE); } It's a full or lite configuration candidate... Let's determine the order value,if any. Integer order = getorder(Metadata); if (order != ) { beanDef.setAttribute(ORDER_ATTRIBUTE,order); } ; }
上面主要是获取元数据,然后判断元数据中是否有Configuration注解. 如果有,返回其属性. 我们判断其属性中proxyBeanMethods是否true,如果是true,那么将其设置为full.
如果配置中带有@Component,@ComponentScan @Import @ImportResource @Bean这几种属性之一,那么就将其设置为lite.
问题5: cglib动态代理做了什么事情呢?
不看源码的情况下,简单可以理解为,去ioc工厂里面通过getBean("car") 查询了看ioc中是否有这个对象,如果有就取出来,不再另创建.
这也是@Configuration 和其他注解类似@Component和@ComponentScan的本质区别:
当在配置类中一个@Bean使用方法的方式引入另一个Bean的时候,就会重复创建Bean
如果加了@Configuration,存在则直接使用.
下面来看个例子
基础类: Car { private String name; Tank tank; String getName() { name; } setName(String name) { this.name = Tank getTank() { tank; } setTank(Tank tank) { this.tank = tank; } } Tank { String name; Tank() { System.out.println(创建一个tank); } name; } }
这是定义的car和tank的基础类
@Configuration @ComponentScan(basePackages = { MainConfig { @Bean("car") Car car() { Car car = Car(); car.setName(zhangsan); 这里调用了Tank类,tank是通过@Bean注解注入的. car.setTank(tank()); car; } @Bean Tank tank() { Tank(); } }
当配置类使用了@Configuration注解的时候,运行main方法
); context.scan(package); Car car2 = (Car) context.getBean(.println(car.getName()); context.close(); } }
当去掉@Configuration注解的时候,再次运行,我们看到创建了两次tank
//@Configuration @ComponentScan(basePackages = { MainConfig { @Bean() car.setTank(tank()); car; } @Bean 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是如何工作的.
invokebeanfactoryPostProcessors( ConfigurableListablebeanfactory beanfactory,调用BeanDeFinitionRegistryPostProcessors 的后置处理器 * 定义已处理的后置处理器 (); 调用beanfactory.getBean实例化配置类的后置处理器(创世界的类ppName),也就是初始化,实例化,赋值属性. currentRegistryProcessors.add(beanfactory.getBean(ppName,BeanDeFinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors,清空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 = (configCandidates.size()); do { // 执行解析 parser.parse(candidates); parser.validate();
然后,接下来创建了一个对象ConfigurationClassparser,这是一个配置类解析器. 下面将使用这个解析器解析配置类.
重点是如何解析的,代码已重点标注出来了.
// 执行解析 parser.parse(candidates);
我们这里是通过注解解析的,所以直接看下面的代码
void parse(Set<BeanDeFinitionHolder> configCandidates) { 循环配置类 (BeanDeFinitionHolder holder : configCandidates) { BeanDeFinition bd = holder.getBeanDeFinition(); 真正的解析bean定义:通过注解元数据解析 (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..getName())) { Recursively process any member (nested) classes first processMemberClasses(configClass,sourceClass,filter); } Process any @PropertySource annotations // 2. 处理@PropertySource 注解,判断元数据是否带有@PropertySource注解 (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(),PropertySources.)) { .environment instanceof ConfigurableEnvironment) { processpropertySource(propertySource); } { 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.if (!componentScans.isEmpty() && !.conditionEvaluator.shouldSkip(sourceClass.getMetadata(),ConfigurationPhase.REGISTER_BEAN)) { (AnnotationAttributes componentScan : componentScans) { The config class is annotated with @ComponentScan -> perform the scan immediately 解析扫描出来的类,将其解析为BeanDeFinitionHolder对象,并放入到scannedBeanDeFinitions中 这正的解析ComponentScans和ComponentScan中的配置 Set<BeanDeFinitionHolder> scannedBeanDeFinitions = .componentScanParser.parse(componentScan,sourceClass.getMetadata().getClassName()); 循环处理包扫描出来的bean定义 Check the set of scanned deFinitions for any further config classes and parse recursively if needed (BeanDeFinitionHolder holder : scannedBeanDeFinitions) { BeanDeFinition bdCand = holder.getBeanDeFinition().getoriginatingBeanDeFinition(); if (bdCand == ) { bdCand = holder.getBeanDeFinition(); } 判断当前扫描出来的是不是一个配置类,如果是的话,直接进行递归解析. if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand,1)">.MetadataReaderFactory)) { parse(bdCand.getBeanClassName(),holder.getBeanName()); } } } } // 4. 处理@Import注解 Process any @Import annotations processImports(configClass,getImports(sourceClass),filter,1)">); // 5. 处理@ImportResource注解 Process any @ImportResource annotations AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(),ImportResource.if (importResource != ) { String[] resources = importResource.getStringArray(locations); Class<? extends BeanDeFinitionReader> readerClass = importResource.getClass(reader (String resource : resources) { String resolvedResource = .environment.resolverequiredPlaceholders(resource); configClass.addImportedResource(resolvedResource,readerClass); } } // 6. 处理@Bean注解 Process individual @Bean methods Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); (MethodMetadata methodMetadata : beanMethods) { configClass.addBeanMethod( BeanMethod(methodMetadata,configClass)); } 处理默认方法 Process default methods on interfaces processInterfaces(configClass,sourceClass); 处理超类 Process superclass,if any (sourceClass.getMetadata().hasSuperClass()) { String superclass = sourceClass.getMetadata().getSuperClassName(); if (superclass != null && !superclass.startsWith(java") && !.kNownSuperclasses.containsKey(superclass)) { .kNownSuperclasses.put(superclass,configClass); Superclass found,return its annotation Metadata and recurse sourceClass.getSuperClass(); } } No superclass -> processing is complete ; }
下面我们重点看对@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.resourceLoader); // 1. 判断是否有nameGenerator注解 为扫描器设置beanName的生成器对象,并赋值给scanner,BeanNameGenerator的作用是为bean deFinitions生成Bean名字的接口 Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass(nameGenerator); boolean useInheritedGenerator = (BeanNameGenerator. generatorClass); scanner.setBeanNameGenerator(useInheritedGenerator ? .beanNameGenerator : BeanUtils.instantiateClass(generatorClass)); // 2. 判断是否有scopedProxy注解 ScopedProxyMode scopedProxyMode = componentScan.getEnum(scopedProxyif (scopedProxyMode != ScopedProxyMode.DEFAULT) { scanner.setScopedProxyMode(scopedProxyMode); } { 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 (TypeFilter typeFilter : typeFiltersFor(filter)) { scanner.addIncludeFilter(typeFilter); } } // 4. 判断属性总是否有excludeFilters属性,有的话放到scnanner中 设置componentScan中排除的过滤器 excludeFilters (TypeFilter typeFilter : typeFiltersFor(filter)) { scanner.addExcludeFilter(typeFilter); } } // 5. 判断是否有lazyInit属性 获取配置类中懒加载初始化的属性 boolean lazyInit = componentScan.getBoolean(lazyInit (lazyInit) { scanner.getBeanDeFinitionDefaults().setLazyInit(); } Set<String> basePackages = (); // 6. 判断是否有basePackages属性 获取basePackages属性,也就是我们定义的包扫描路径 String[] basePackagesArray = componentScan.getStringArray(basePackages (String pkg : basePackagesArray) { String[] tokenized = StringUtils.tokenizetoStringArray(.environment.resolvePlaceholders(pkg),ConfigurableApplicationContext.CONfig_LOCATION_DELIMITERS); Collections.addAll(basePackages,tokenized); } for (Class<?> clazz : componentScan.getClassArray(basePackageClasses)) { basePackages.add(ClassUtils.getPackageName(clazz)); } (basePackages.isEmpty()) { basePackages.add(ClassUtils.getPackageName(declaringClass)); } scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false,1)">) { @Override boolean matchClassName(String className) { declaringClass.equals(className); } }); // 调用scanner.doScan()方法,扫描basePackages包 scanner.doScan(StringUtils.toStringArray(basePackages)); }
调用doScan方法扫描配置类. 我们来看看主要做了哪些事情
第一步: 找到所有候选的BeanDeFinition.
上面解析出了@ComponentScan注解传递过来的basePackages包. 扫描包中所有的类,得到候选类.
扫描的时候做了几件事呢? 看最上图最右侧部分. 这扫描出来就是我们的目标类.
第二步: 解析这些准目标类.
* * 设置默认的bean定义的信息 * Apply the provided default values to this bean. * @param defaults the default settings to apply * @since 2.5 applyDefaults(BeanDeFinitionDefaults defaults) { 设置这个类是不是懒加载的 Boolean lazyInit = defaults.getLazyInit(); if (lazyInit != ) { setLazyInit(lazyInit); } 设置默认的自动装配方式 setAutowireMode(defaults.getAutowireMode()); setDependencyCheck(defaults.getDependencyCheck()); 设置初始化方法的名称 setinitMethodName(defaults.getinitMethodName()); 是否可以调用InitMethod方法 setEnforceInitMethod(); setDestroyMethodName(defaults.getDestroyMethodName()); 是否可以调用DestroyMethod方法 setEnforceDestroyMethod(); }
第四步: 将解析出来的bean定义注册到ioc容器中
这里就调用了BeanDeFinitionReaderUtils.registerBeanDeFinition注册bean定义. 之前注册过配置类,这里和其是一样的. 所以不再赘述了
这里有两个细节:
1. excludeFilter中排除了自己
定义了一个类路径扫描器ClasspathBeanDeFinitionScanner 这里的scanner用于读取配置类 ClasspathBeanDeFinitionScanner scanner = .registry,componentScan.getBoolean(useDefaultFilters"),1)">this.environment,1)">.resourceLoader); 1. 判断是否有nameGenerator注解 为扫描器设置beanName的生成器对象 Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass(.beanNameGenerator : BeanUtils.instantiateClass(generatorClass)); 2. 判断是否有scopedProxy注解 ScopedProxyMode scopedProxyMode = componentScan.getEnum()); 3. 判断属性中是否有includeFilters属性,有的话就添加到scanner中 (TypeFilter typeFilter : typeFiltersFor(filter)) { scanner.addIncludeFilter(typeFilter); } } 4. 判断属性总是否有excludeFilters属性,有的话放到scnanner中 (TypeFilter typeFilter : typeFiltersFor(filter)) { scanner.addExcludeFilter(typeFilter); } } 5. 判断是否有lazyInit属性 6. 判断是否有basePackages属性 (basePackages.isEmpty()) { basePackages.add(ClassUtils.getPackageName(declaringClass)); } 想ExcludeFilter中添加默认的排除类, scanner.addExcludeFilter() { @Override protected boolean matchClassName(String className) { /** * declaringClass就是配置类MainConfig,也就是说. 如果当前类是配置类,那么就会排除掉 * 这是一个钩子方法,现在不会调用. 后面才调用 * 在哪里调用呢? */ return declaringClass.equals(className); } }); 调用scanner.doScan()方法,扫描basePackages包 scanner.doScan(StringUtils.toStringArray(basePackages)); }在解析配置类的时候,除了@ComponentScan注解中定义的ExcludeFilter和IncludeFilter以外,还有默认的排除类. 如上加粗字体的部分. 这里是排除了配置类本身,我们这里的配置类是MainConfig,也就说,会排除掉自己.
@Override boolean matchClassName(String className) { * * declaringClass就是配置类MainConfig,现在不会调用. 后面才调用 * 在哪里调用呢? 先记住这个钩子方法matchClassName */ declaringClass.equals(className); }matchClassName是一个钩子方法. 在执行到这里的时候,不会真的去执行. 什么时候执行呢? 后面调用doScan的时候执行.
protected Set<BeanDeFinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages,1)">At least one base package must be specified); Set<BeanDeFinitionHolder> beanDeFinitions = 循环包路径 (String basePackage : basePackages) { // 第一步: 找到所有候选的BeanDeFinition * * 在候选的配置类中,排除掉了自己,同时包含了默认的配置类 Set<BeanDeFinition> candidates = findCandidateComponents(basePackage);在寻找候选配置类的时候,进行了排除了配置类本身.
public Set<BeanDeFinition> findCandidateComponents(String basePackage) { this.componentsIndex != indexSupportsIncludeFilters()) { return addCandidateComponentsFromIndex(.componentsIndex,basePackage); } // 扫描basePackages,获取候选类 return scanCandidateComponents(basePackage); } }进入这个方法
private Set<BeanDeFinition> scanCandidateComponents(String basePackage) { Set<BeanDeFinition> candidates = 第一步: 将com.lxl.www.iocbeanlifecicle转换成了物理路径com/lxl/www/iocbeanlifecicle String packageSearchPath = ResourcePatternResolver.CLAsspATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + .resourcePattern; 第二步: .getResources(...)读取到了包下所有的类 Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); (Resource resource : resources) { (traceEnabled) { logger.trace(Scanning resource); } 第三步: 判断这个类是否是可读的? (resource.isReadable()) { { MetadataReader MetadataReader = getMetadataReaderFactory().getMetadataReader(resource); 第四步: 判断这个类是否是我们要排除的 或者 包含的 if (isCandidateComponent(MetadataReader)) { 通过scnner扫描出来的beanDeFinition是ScannedGenericBeanDeFinition类型 ScannedGenericBeanDeFinition sbd = ScannedGenericBeanDeFinition(MetadataReader); 设置sbd的原类路径 sbd.setSource(resource);在第四步的时候调用了isCandidateComponent(MetadataReader,这里就判断了是否是包含的类,或者是排除的类
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); } } ; }紫色加错的部分是就是判读是否符合排除的类. 红色加错的部分是判断是否是包含的类.
先来看紫色的部分,排除的类
boolean match(MetadataReader MetadataReader,MetadataReaderFactory MetadataReaderFactory) throws IOException { This method optimizes avoiding unnecessary creation of ClassReaders as well as visiting over those readers. (matchSelf(MetadataReader)) { ; } ClassMetadata Metadata = MetadataReader.getClassMetadata(); // 排除配置类. if (matchClassName(Metadata.getClassName())) { return true; }看到了么,这里调用了matchClassName. 这就是上面定义的钩子方法,
@Override boolean matchClassName(String className) { declaringClass.equals(className); }此时declaringClass表示的是当前的配置类,className表示的是目标类,如果当前目标类 == 配置类,那么就放回true. 返回true,则会排除掉
2. includeFilter中包含了默认的配置类
下面来看红色加错的部分
; }
我们看到这里有this.includeFilters.包含的过滤器. 这里面是有值的
我们没有在配置类MainConfig上设置includeFilter啊,这里面怎么会有值呢?
这是因为我们有默认包含的过滤器,下面看看默认包含的过滤器是在哪里设置的.
首先从入口类点击AnnotationConfigApplicationContext
然后在点击this();
再点击ClasspathBeanDeFinitionScanner
然后一路点击三个this(...)
最后看到上图 registerDefaultFilter();注册默认的过滤器
@SuppressWarnings(unchecked registerDefaultFilters() { 注册默认的filter---第一个: 在includeFilter中增加了Component this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl = ClasspathScanningCandidateComponentProvider..getClassLoader(); { 注册默认的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); } (ClassNotFoundException ex) { JSR-250 1.1 API (as included in Java EE 6) not available - simply skip. } 注册默认的filter---第三个:在includeFilter中增加了 javax.inject.Named this.includeFilters.add(new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named",false)); logger.trace(JSR-330 'javax.inject.Named' annotation found and supported for component scanning JSR-330 API not available - simply skip. } }如上图看到,注册了3个默认的过滤器. 分别是Component,ManagedBean,Named. 他们都是注解类型的过滤器AnnotationTypeFilter
其中javax.annotation.ManagedBean和javax.inject.Named是jdk提供给我们的.
到此为止,就将MainConfig配置类解析完并注册到ioc容器中了.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。