从 Spring2.0 以后的版本中,Spring 也引入了基于注解(Annotation)方式的配置,注解(Annotation)是 JDK1.5 中引入的一个新特性,用于简化 Bean 的配置,可以取代 XML 配置文件。开发人员对注解(Annotation)的态度也是萝卜青菜各有所爱,个人认为注解可以大大简化配置,提高开发速度,但也给后期维护增加了难度。目前来说 XML 方式发展的相对成熟,方便于统一管理。随着 Spring Boot 的兴起,基于注解的开发甚至实现了零配置。但作为个人的习惯而言,还是倾向于 XML 配置文件和注解(Annotation)相互配合使用。Spring IOC 容器对于类级别的注解和类内部的注解分以下两种处理策略:
1)、类级别的注解:如@Component、@Repository、@Controller、@Service 以及 JavaEE6 的@ManagedBean 和@Named 注解,都是添加在类上面的类级别注解,Spring 容器根据注解的过滤规则扫描读取注解 Bean 定义类,并将其注册到 Spring IOC 容器中。
2)、类内部的注解:如@Autowire、@Value、@Resource 以及 EJB 和 WebService 相关的注解等,都是添加在类内部的字段或者方法上的类内部注解,SpringIOC 容器通过 Bean 后置注解处理器解析Bean 内部的注解。下面将根据这两种处理策略,分别分析 Spring 处理注解相关的源码。
定位 Bean 扫描路径
在 Spring 中 管 理 注 解 Bean 定 义 的 容 器 有 两 个 : AnnotationConfigApplicationContext 和AnnotationConfigWebApplicationContex。这两个类是专门处理 Spring 注解方式配置的容器,直接依赖于注解作为容器配置信息来源的 IOC 容器。AnnotationConfigWebApplicationContext 是AnnotationConfigApplicationContext 的 Web 版本,两者的用法以及对注解的处理方式几乎没有差别。现在我们以 AnnotationConfigApplicationContext 为例看看它的源码:
publicclassAnnotationConfigApplicationContextextendsGenericApplicationContextimplementsAnnotationConfigRegistry{//保存一个读取注解的Bean定义读取器,并将其设置到容器中privatefinalAnnotatedBeanDefinitionReader reader;//保存一个扫描指定类路径中注解Bean定义的扫描器,并将其设置到容器中privatefinalClassPathBeanDefinitionScanner scanner;/**
* Create a new AnnotationConfigApplicationContext that needs to be populated
* through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
*///默认构造函数,初始化一个空容器,容器不包含任何 Bean 信息,需要在稍后通过调用其register()//方法注册配置类,并调用refresh()方法刷新容器,触发容器对注解Bean的载入、解析和注册过程publicAnnotationConfigApplicationContext(){this.reader =newAnnotatedBeanDefinitionReader(this);this.scanner =newClassPathBeanDefinitionScanner(this);}/**
* Create a new AnnotationConfigApplicationContext with the given DefaultListableBeanFactory.
* @param beanFactory the DefaultListableBeanFactory instance to use for this context
*/publicAnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory){super(beanFactory);this.reader =newAnnotatedBeanDefinitionReader(this);this.scanner =newClassPathBeanDefinitionScanner(this);}/**
* Create a new AnnotationConfigApplicationContext, deriving bean definitions
* from the given annotated classes and automatically refreshing the context.
* @param annotatedClasses one or more annotated classes,
* e.g. {@link Configuration @Configuration} classes
*///最常用的构造函数,通过将涉及到的配置类传递给该构造函数,以实现将相应配置类中的Bean自动注册到容器中publicAnnotationConfigApplicationContext(Class<?>... annotatedClasses){this();register(annotatedClasses);refresh();}/**
* Create a new AnnotationConfigApplicationContext, scanning for bean definitions
* in the given packages and automatically refreshing the context.
* @param basePackages the packages to check for annotated classes
*///该构造函数会自动扫描以给定的包及其子包下的所有类,并自动识别所有的Spring Bean,将其注册到容器中publicAnnotationConfigApplicationContext(String... basePackages){this();scan(basePackages);refresh();}/**
* {@inheritDoc}
* <p>Delegates given environment to underlying {@link AnnotatedBeanDefinitionReader}
* and {@link ClassPathBeanDefinitionScanner} members.
*/@OverridepublicvoidsetEnvironment(ConfigurableEnvironment environment){super.setEnvironment(environment);this.reader.setEnvironment(environment);this.scanner.setEnvironment(environment);}/**
* Provide a custom {@link BeanNameGenerator} for use with {@link AnnotatedBeanDefinitionReader}
* and/or {@link ClassPathBeanDefinitionScanner}, if any.
* <p>Default is {@link org.springframework.context.annotation.AnnotationBeanNameGenerator}.
* <p>Any call to this method must occur prior to calls to {@link #register(Class...)}
* and/or {@link #scan(String...)}.
* @see AnnotatedBeanDefinitionReader#setBeanNameGenerator
* @see ClassPathBeanDefinitionScanner#setBeanNameGenerator
*///为容器的注解Bean读取器和注解Bean扫描器设置Bean名称产生器publicvoidsetBeanNameGenerator(BeanNameGenerator beanNameGenerator){this.reader.setBeanNameGenerator(beanNameGenerator);this.scanner.setBeanNameGenerator(beanNameGenerator);getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);}/**
* Set the {@link ScopeMetadataResolver} to use for detected bean classes.
* <p>The default is an {@link AnnotationScopeMetadataResolver}.
* <p>Any call to this method must occur prior to calls to {@link #register(Class...)}
* and/or {@link #scan(String...)}.
*///为容器的注解Bean读取器和注解Bean扫描器设置作用范围元信息解析器publicvoidsetScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver){this.reader.setScopeMetadataResolver(scopeMetadataResolver);this.scanner.setScopeMetadataResolver(scopeMetadataResolver);}//---------------------------------------------------------------------// Implementation of AnnotationConfigRegistry//---------------------------------------------------------------------/**
* Register one or more annotated classes to be processed.
* <p>Note that {@link #refresh()} must be called in order for the context
* to fully process the new classes.
* @param annotatedClasses one or more annotated classes,
* e.g. {@link Configuration @Configuration} classes
* @see #scan(String...)
* @see #refresh()
*///为容器注册一个要被处理的注解Bean,新注册的Bean,必须手动调用容器的//refresh()方法刷新容器,触发容器对新注册的Bean的处理publicvoidregister(Class<?>... annotatedClasses){Assert.notEmpty(annotatedClasses,"At least one annotated class must be specified");this.reader.register(annotatedClasses);}/**
* Perform a scan within the specified base packages.
* <p>Note that {@link #refresh()} must be called in order for the context
* to fully process the new classes.
* @param basePackages the packages to check for annotated classes
* @see #register(Class...)
* @see #refresh()
*///扫描指定包路径及其子包下的注解类,为了使新添加的类被处理,必须手动调用//refresh()方法刷新容器publicvoidscan(String... basePackages){Assert.notEmpty(basePackages,"At least one base package must be specified");this.scanner.scan(basePackages);}//---------------------------------------------------------------------// Convenient methods for registering individual beans//---------------------------------------------------------------------/**
* Register a bean from the given bean class, deriving its metadata from
* class-declared annotations, and optionally providing explicit constructor
* arguments for consideration in the autowiring process.
* <p>The bean name will be generated according to annotated component rules.
* @param annotatedClass the class of the bean
* @param constructorArguments argument values to be fed into Spring's
* constructor resolution algorithm, resolving either all arguments or just
* specific ones, with the rest to be resolved through regular autowiring
* (may be {@code null} or empty)
* @since 5.0
*/public<T>voidregisterBean(Class<T> annotatedClass,Object... constructorArguments){registerBean(null, annotatedClass, constructorArguments);}/**
* Register a bean from the given bean class, deriving its metadata from
* class-declared annotations, and optionally providing explicit constructor
* arguments for consideration in the autowiring process.
* @param beanName the name of the bean (may be {@code null})
* @param annotatedClass the class of the bean
* @param constructorArguments argument values to be fed into Spring's
* constructor resolution algorithm, resolving either all arguments or just
* specific ones, with the rest to be resolved through regular autowiring
* (may be {@code null} or empty)
* @since 5.0
*/public<T>voidregisterBean(@NullableString beanName,Class<T> annotatedClass,Object... constructorArguments){this.reader.doRegisterBean(annotatedClass,null, beanName,null,
bd ->{for(Object arg : constructorArguments){
bd.getConstructorArgumentValues().addGenericArgumentValue(arg);}});}@Overridepublic<T>voidregisterBean(@NullableString beanName,Class<T> beanClass,@NullableSupplier<T> supplier,BeanDefinitionCustomizer... customizers){this.reader.doRegisterBean(beanClass, supplier, beanName,null, customizers);}}
/**
* Register one or more annotated classes to be processed.
* <p>Calls to {@code register} are idempotent; adding the same
* annotated class more than once has no additional effect.
* @param annotatedClasses one or more annotated classes,
* e.g. {@link Configuration @Configuration} classes
*///注册多个注解Bean定义类publicvoidregister(Class<?>... annotatedClasses){for(Class<?> annotatedClass : annotatedClasses){registerBean(annotatedClass);}}/**
* Register a bean from the given bean class, deriving its metadata from
* class-declared annotations.
* @param annotatedClass the class of the bean
*///注册一个注解Bean定义类publicvoidregisterBean(Class<?> annotatedClass){doRegisterBean(annotatedClass,null,null,null);}/**
* Register a bean from the given bean class, deriving its metadata from
* class-declared annotations, using the given supplier for obtaining a new
* instance (possibly declared as a lambda expression or method reference).
* @param annotatedClass the class of the bean
* @param instanceSupplier a callback for creating an instance of the bean
* (may be {@code null})
* @since 5.0
*/public<T>voidregisterBean(Class<T> annotatedClass,@NullableSupplier<T> instanceSupplier){doRegisterBean(annotatedClass, instanceSupplier,null,null);}/**
* Register a bean from the given bean class, deriving its metadata from
* class-declared annotations, using the given supplier for obtaining a new
* instance (possibly declared as a lambda expression or method reference).
* @param annotatedClass the class of the bean
* @param name an explicit name for the bean
* @param instanceSupplier a callback for creating an instance of the bean
* (may be {@code null})
* @since 5.0
*/public<T>voidregisterBean(Class<T> annotatedClass,String name,@NullableSupplier<T> instanceSupplier){doRegisterBean(annotatedClass, instanceSupplier, name,null);}/**
* Register a bean from the given bean class, deriving its metadata from
* class-declared annotations.
* @param annotatedClass the class of the bean
* @param qualifiers specific qualifier annotations to consider,
* in addition to qualifiers at the bean class level
*///Bean定义读取器注册注解Bean定义的入口方法@SuppressWarnings("unchecked")publicvoidregisterBean(Class<?> annotatedClass,Class<?extendsAnnotation>... qualifiers){doRegisterBean(annotatedClass,null,null, qualifiers);}/**
* Register a bean from the given bean class, deriving its metadata from
* class-declared annotations.
* @param annotatedClass the class of the bean
* @param name an explicit name for the bean
* @param qualifiers specific qualifier annotations to consider,
* in addition to qualifiers at the bean class level
*///Bean定义读取器向容器注册注解Bean定义类@SuppressWarnings("unchecked")publicvoidregisterBean(Class<?> annotatedClass,String name,Class<?extendsAnnotation>... qualifiers){doRegisterBean(annotatedClass,null, name, qualifiers);}/**
* Register a bean from the given bean class, deriving its metadata from
* class-declared annotations.
* @param annotatedClass the class of the bean
* @param instanceSupplier a callback for creating an instance of the bean
* (may be {@code null})
* @param name an explicit name for the bean
* @param qualifiers specific qualifier annotations to consider, if any,
* in addition to qualifiers at the bean class level
* @param definitionCustomizers one or more callbacks for customizing the
* factory's {@link BeanDefinition}, e.g. setting a lazy-init or primary flag
* @since 5.0
*///Bean定义读取器向容器注册注解Bean定义类<T>voiddoRegisterBean(Class<T> annotatedClass,@NullableSupplier<T> instanceSupplier,@NullableString name,@NullableClass<?extendsAnnotation>[] qualifiers,BeanDefinitionCustomizer... definitionCustomizers){//根据指定的注解Bean定义类,创建Spring容器中对注解Bean的封装的数据结构AnnotatedGenericBeanDefinition abd =newAnnotatedGenericBeanDefinition(annotatedClass);if(this.conditionEvaluator.shouldSkip(abd.getMetadata())){return;}
abd.setInstanceSupplier(instanceSupplier);//解析注解Bean定义的作用域,若@Scope("prototype"),则Bean为原型类型;//若@Scope("singleton"),则Bean为单态类型ScopeMetadata scopeMetadata =this.scopeMetadataResolver.resolveScopeMetadata(abd);//为注解Bean定义设置作用域
abd.setScope(scopeMetadata.getScopeName());//为注解Bean定义生成Bean名称String beanName =(name !=null? name :this.beanNameGenerator.generateBeanName(abd,this.registry));//处理注解Bean定义中的通用注解AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);//如果在向容器注册注解Bean定义时,使用了额外的限定符注解,则解析限定符注解。//主要是配置的关于autowiring自动依赖注入装配的限定条件,即@Qualifier注解//Spring自动依赖注入装配默认是按类型装配,如果使用@Qualifier则按名称if(qualifiers !=null){for(Class<?extendsAnnotation> qualifier : qualifiers){//如果配置了@Primary注解,设置该Bean为autowiring自动依赖注入装//配时的首选if(Primary.class== qualifier){
abd.setPrimary(true);}//如果配置了@Lazy注解,则设置该Bean为非延迟初始化,如果没有配置,//则该Bean为预实例化elseif(Lazy.class== qualifier){
abd.setLazyInit(true);}//如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一//个autowiring自动依赖注入装配限定符,该Bean在进autowiring//自动依赖注入装配时,根据名称装配限定符指定的Beanelse{
abd.addQualifier(newAutowireCandidateQualifier(qualifier));}}}for(BeanDefinitionCustomizer customizer : definitionCustomizers){
customizer.customize(abd);}//创建一个指定Bean名称的Bean定义对象,封装注解Bean定义类数据BeanDefinitionHolder definitionHolder =newBeanDefinitionHolder(abd, beanName);//根据注解Bean定义类中配置的作用域,创建相应的代理对象
definitionHolder =AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder,this.registry);//向IOC容器注册注解Bean类定义对象BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder,this.registry);}
publicclassClassPathBeanDefinitionScannerextendsClassPathScanningCandidateComponentProvider{/**
* Create a new {@code ClassPathBeanDefinitionScanner} for the given bean factory.
* @param registry the {@code BeanFactory} to load bean definitions into, in the form
* of a {@code BeanDefinitionRegistry}
*///创建一个类路径Bean定义扫描器publicClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry){this(registry,true);}/**
* Create a new {@code ClassPathBeanDefinitionScanner} for the given bean factory.
* <p>If the passed-in bean factory does not only implement the
* {@code BeanDefinitionRegistry} interface but also the {@code ResourceLoader}
* interface, it will be used as default {@code ResourceLoader} as well. This will
* usually be the case for {@link org.springframework.context.ApplicationContext}
* implementations.
* <p>If given a plain {@code BeanDefinitionRegistry}, the default {@code ResourceLoader}
* will be a {@link org.springframework.core.io.support.PathMatchingResourcePatternResolver}.
* <p>If the passed-in bean factory also implements {@link EnvironmentCapable} its
* environment will be used by this reader. Otherwise, the reader will initialize and
* use a {@link org.springframework.core.env.StandardEnvironment}. All
* {@code ApplicationContext} implementations are {@code EnvironmentCapable}, while
* normal {@code BeanFactory} implementations are not.
* @param registry the {@code BeanFactory} to load bean definitions into, in the form
* of a {@code BeanDefinitionRegistry}
* @param useDefaultFilters whether to include the default filters for the
* {@link org.springframework.stereotype.Component @Component},
* {@link org.springframework.stereotype.Repository @Repository},
* {@link org.springframework.stereotype.Service @Service}, and
* {@link org.springframework.stereotype.Controller @Controller} stereotype annotations
* @see #setResourceLoader
* @see #setEnvironment
*///为容器创建一个类路径Bean定义扫描器,并指定是否使用默认的扫描过滤规则。//即Spring默认扫描配置:@Component、@Repository、@Service、@Controller//注解的Bean,同时也支持JavaEE6的@ManagedBean和JSR-330的@Named注解publicClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry,boolean useDefaultFilters){this(registry, useDefaultFilters,getOrCreateEnvironment(registry));}/**
* Create a new {@code ClassPathBeanDefinitionScanner} for the given bean factory and
* using the given {@link Environment} when evaluating bean definition profile metadata.
* <p>If the passed-in bean factory does not only implement the {@code
* BeanDefinitionRegistry} interface but also the {@link ResourceLoader} interface, it
* will be used as default {@code ResourceLoader} as well. This will usually be the
* case for {@link org.springframework.context.ApplicationContext} implementations.
* <p>If given a plain {@code BeanDefinitionRegistry}, the default {@code ResourceLoader}
* will be a {@link org.springframework.core.io.support.PathMatchingResourcePatternResolver}.
* @param registry the {@code BeanFactory} to load bean definitions into, in the form
* of a {@code BeanDefinitionRegistry}
* @param useDefaultFilters whether to include the default filters for the
* {@link org.springframework.stereotype.Component @Component},
* {@link org.springframework.stereotype.Repository @Repository},
* {@link org.springframework.stereotype.Service @Service}, and
* {@link org.springframework.stereotype.Controller @Controller} stereotype annotations
* @param environment the Spring {@link Environment} to use when evaluating bean
* definition profile metadata
* @since 3.1
* @see #setResourceLoader
*/publicClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry,boolean useDefaultFilters,Environment environment){this(registry, useDefaultFilters, environment,(registry instanceofResourceLoader?(ResourceLoader) registry :null));}/**
* Create a new {@code ClassPathBeanDefinitionScanner} for the given bean factory and
* using the given {@link Environment} when evaluating bean definition profile metadata.
* @param registry the {@code BeanFactory} to load bean definitions into, in the form
* of a {@code BeanDefinitionRegistry}
* @param useDefaultFilters whether to include the default filters for the
* {@link org.springframework.stereotype.Component @Component},
* {@link org.springframework.stereotype.Repository @Repository},
* {@link org.springframework.stereotype.Service @Service}, and
* {@link org.springframework.stereotype.Controller @Controller} stereotype annotations
* @param environment the Spring {@link Environment} to use when evaluating bean
* definition profile metadata
* @param resourceLoader the {@link ResourceLoader} to use
* @since 4.3.6
*/publicClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry,boolean useDefaultFilters,Environment environment,@NullableResourceLoader resourceLoader){Assert.notNull(registry,"BeanDefinitionRegistry must not be null");//为容器设置加载Bean定义的注册器this.registry = registry;if(useDefaultFilters){registerDefaultFilters();}setEnvironment(environment);//为容器设置资源加载器setResourceLoader(resourceLoader);}/**
* Perform a scan within the specified base packages.
* @param basePackages the packages to check for annotated classes
* @return number of beans registered
*///调用类路径Bean定义扫描器入口方法publicintscan(String... basePackages){//获取容器中已经注册的Bean个数int beanCountAtScanStart =this.registry.getBeanDefinitionCount();//启动扫描器扫描给定包doScan(basePackages);// Register annotation config processors, if necessary.//注册注解配置(Annotation config)处理器if(this.includeAnnotationConfig){AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);}//返回注册的Bean个数return(this.registry.getBeanDefinitionCount()- beanCountAtScanStart);}/**
* Perform a scan within the specified base packages,
* returning the registered bean definitions.
* <p>This method does <i>not</i> register an annotation config processor
* but rather leaves this up to the caller.
* @param basePackages the packages to check for annotated classes
* @return set of beans registered if any for tooling registration purposes (never {@code null})
*///类路径Bean定义扫描器扫描给定包及其子包protectedSet<BeanDefinitionHolder>doScan(String... basePackages){Assert.notEmpty(basePackages,"At least one base package must be specified");//创建一个集合,存放扫描到Bean定义的封装类Set<BeanDefinitionHolder> beanDefinitions =newLinkedHashSet<>();//遍历扫描所有给定的包for(String basePackage : basePackages){//调用父类ClassPathScanningCandidateComponentProvider的方法//扫描给定类路径,获取符合条件的Bean定义Set<BeanDefinition> candidates =findCandidateComponents(basePackage);//遍历扫描到的Beanfor(BeanDefinition candidate : candidates){//获取Bean定义类中@Scope注解的值,即获取Bean的作用域ScopeMetadata scopeMetadata =this.scopeMetadataResolver.resolveScopeMetadata(candidate);//为Bean设置注解配置的作用域
candidate.setScope(scopeMetadata.getScopeName());//为Bean生成名称String beanName =this.beanNameGenerator.generateBeanName(candidate,this.registry);//如果扫描到的Bean不是Spring的注解Bean,则为Bean设置默认值,//设置Bean的自动依赖注入装配属性等if(candidate instanceofAbstractBeanDefinition){postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);}//如果扫描到的Bean是Spring的注解Bean,则处理其通用的Spring注解if(candidate instanceofAnnotatedBeanDefinition){//处理注解Bean中通用的注解,在分析注解Bean定义类读取器时已经分析过AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);}//根据Bean名称检查指定的Bean是否需要在容器中注册,或者在容器中冲突if(checkCandidate(beanName, candidate)){BeanDefinitionHolder definitionHolder =newBeanDefinitionHolder(candidate, beanName);//根据注解中配置的作用域,为Bean应用相应的代理模式
definitionHolder =AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder,this.registry);
beanDefinitions.add(definitionHolder);//向容器注册扫描到的BeanregisterBeanDefinition(definitionHolder,this.registry);}}}return beanDefinitions;}}
publicclassClassPathScanningCandidateComponentProviderimplementsEnvironmentCapable,ResourceLoaderAware{//保存过滤规则要包含的注解,即Spring默认的@Component、@Repository、@Service、//@Controller注解的Bean,以及JavaEE6的@ManagedBean和JSR-330的@Named注解privatefinalList<TypeFilter> includeFilters =newLinkedList<>();//保存过滤规则要排除的注解privatefinalList<TypeFilter> excludeFilters =newLinkedList<>();/**
* Create a ClassPathScanningCandidateComponentProvider with a {@link StandardEnvironment}.
* @param useDefaultFilters whether to register the default filters for the
* {@link Component @Component}, {@link Repository @Repository},
* {@link Service @Service}, and {@link Controller @Controller}
* stereotype annotations
* @see #registerDefaultFilters()
*///构造方法,该方法在子类ClassPathBeanDefinitionScanner的构造方法中被调用publicClassPathScanningCandidateComponentProvider(boolean useDefaultFilters){this(useDefaultFilters,newStandardEnvironment());}/**
* Create a ClassPathScanningCandidateComponentProvider with the given {@link Environment}.
* @param useDefaultFilters whether to register the default filters for the
* {@link Component @Component}, {@link Repository @Repository},
* {@link Service @Service}, and {@link Controller @Controller}
* stereotype annotations
* @param environment the Environment to use
* @see #registerDefaultFilters()
*/publicClassPathScanningCandidateComponentProvider(boolean useDefaultFilters,Environment environment){//如果使用Spring默认的过滤规则,则向容器注册过滤规则if(useDefaultFilters){registerDefaultFilters();}setEnvironment(environment);setResourceLoader(null);}/**
* Register the default filter for {@link Component @Component}.
* <p>This will implicitly register all annotations that have the
* {@link Component @Component} meta-annotation including the
* {@link Repository @Repository}, {@link Service @Service}, and
* {@link Controller @Controller} stereotype annotations.
* <p>Also supports Java EE 6's {@link javax.annotation.ManagedBean} and
* JSR-330's {@link javax.inject.Named} annotations, if available.
*
*///向容器注册过滤规则@SuppressWarnings("unchecked")protectedvoidregisterDefaultFilters(){//向要包含的过滤规则中添加@Component注解类,注意Spring中@Repository//@Service和@Controller都是Component,因为这些注解都添加了@Component注解this.includeFilters.add(newAnnotationTypeFilter(Component.class));//获取当前类的类加载器ClassLoader cl =ClassPathScanningCandidateComponentProvider.class.getClassLoader();try{//向要包含的过滤规则添加JavaEE6的@ManagedBean注解this.includeFilters.add(newAnnotationTypeFilter(((Class<?extendsAnnotation>)ClassUtils.forName("javax.annotation.ManagedBean", cl)),false));
logger.debug("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{//向要包含的过滤规则添加@Named注解this.includeFilters.add(newAnnotationTypeFilter(((Class<?extendsAnnotation>)ClassUtils.forName("javax.inject.Named", cl)),false));
logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");}catch(ClassNotFoundException ex){// JSR-330 API not available - simply skip.}}/**
* Scan the class path for candidate components.
* @param basePackage the package to check for annotated classes
* @return a corresponding Set of autodetected bean definitions
*///扫描给定类路径的包publicSet<BeanDefinition>findCandidateComponents(String basePackage){if(this.componentsIndex !=null&&indexSupportsIncludeFilters()){returnaddCandidateComponentsFromIndex(this.componentsIndex, basePackage);}else{returnscanCandidateComponents(basePackage);}}privateSet<BeanDefinition>addCandidateComponentsFromIndex(CandidateComponentsIndex index,String basePackage){//创建存储扫描到的类的集合Set<BeanDefinition> candidates =newLinkedHashSet<>();try{Set<String> types =newHashSet<>();for(TypeFilter filter :this.includeFilters){String stereotype =extractStereotype(filter);if(stereotype ==null){thrownewIllegalArgumentException("Failed to extract stereotype from "+ filter);}
types.addAll(index.getCandidateTypes(basePackage, stereotype));}boolean traceEnabled = logger.isTraceEnabled();boolean debugEnabled = logger.isDebugEnabled();for(String type : types){//为指定资源获取元数据读取器,元信息读取器通过汇编(ASM)读//取资源元信息MetadataReader metadataReader =getMetadataReaderFactory().getMetadataReader(type);//如果扫描到的类符合容器配置的过滤规则if(isCandidateComponent(metadataReader)){//通过汇编(ASM)读取资源字节码中的Bean定义元信息AnnotatedGenericBeanDefinition sbd =newAnnotatedGenericBeanDefinition(
metadataReader.getAnnotationMetadata());if(isCandidateComponent(sbd)){if(debugEnabled){
logger.debug("Using candidate component class from index: "+ type);}
candidates.add(sbd);}else{if(debugEnabled){
logger.debug("Ignored because not a concrete top-level class: "+ type);}}}else{if(traceEnabled){
logger.trace("Ignored because matching an exclude filter: "+ type);}}}}catch(IOException ex){thrownewBeanDefinitionStoreException("I/O failure during classpath scanning", ex);}return candidates;}/**
* Determine whether the given class does not match any exclude filter
* and does match at least one include filter.
* @param metadataReader the ASM ClassReader for the class
* @return whether the class qualifies as a candidate component
*///判断元信息读取器读取的类是否符合容器定义的注解过滤规则protectedbooleanisCandidateComponent(MetadataReader metadataReader)throwsIOException{//如果读取的类的注解在排除注解过滤规则中,返回falsefor(TypeFilter tf :this.excludeFilters){if(tf.match(metadataReader,getMetadataReaderFactory())){returnfalse;}}//如果读取的类的注解在包含的注解的过滤规则中,则返回turefor(TypeFilter tf :this.includeFilters){if(tf.match(metadataReader,getMetadataReaderFactory())){returnisConditionMatch(metadataReader);}}//如果读取的类的注解既不在排除规则,也不在包含规则中,则返回falsereturnfalse;}}
/**
* Register a {@link org.springframework.beans.factory.config.BeanDefinition} for
* any classes specified by {@link #register(Class...)} and scan any packages
* specified by {@link #scan(String...)}.
* <p>For any values specified by {@link #setConfigLocation(String)} or
* {@link #setConfigLocations(String[])}, attempt first to load each location as a
* class, registering a {@code BeanDefinition} if class loading is successful,
* and if class loading fails (i.e. a {@code ClassNotFoundException} is raised),
* assume the value is a package and attempt to scan it for annotated classes.
* <p>Enables the default set of annotation configuration post processors, such that
* {@code @Autowired}, {@code @Required}, and associated annotations can be used.
* <p>Configuration class bean definitions are registered with generated bean
* definition names unless the {@code value} attribute is provided to the stereotype
* annotation.
* @param beanFactory the bean factory to load bean definitions into
* @see #register(Class...)
* @see #scan(String...)
* @see #setConfigLocation(String)
* @see #setConfigLocations(String[])
* @see AnnotatedBeanDefinitionReader
* @see ClassPathBeanDefinitionScanner
*///载入注解Bean定义资源@OverrideprotectedvoidloadBeanDefinitions(DefaultListableBeanFactory beanFactory){//为容器设置注解Bean定义读取器AnnotatedBeanDefinitionReader reader =getAnnotatedBeanDefinitionReader(beanFactory);//为容器设置类路径Bean定义扫描器ClassPathBeanDefinitionScanner scanner =getClassPathBeanDefinitionScanner(beanFactory);//获取容器的Bean名称生成器BeanNameGenerator beanNameGenerator =getBeanNameGenerator();//为注解Bean定义读取器和类路径扫描器设置Bean名称生成器if(beanNameGenerator !=null){
reader.setBeanNameGenerator(beanNameGenerator);
scanner.setBeanNameGenerator(beanNameGenerator);
beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);}//获取容器的作用域元信息解析器ScopeMetadataResolver scopeMetadataResolver =getScopeMetadataResolver();//为注解Bean定义读取器和类路径扫描器设置作用域元信息解析器if(scopeMetadataResolver !=null){
reader.setScopeMetadataResolver(scopeMetadataResolver);
scanner.setScopeMetadataResolver(scopeMetadataResolver);}if(!this.annotatedClasses.isEmpty()){if(logger.isInfoEnabled()){
logger.info("Registering annotated classes: ["+StringUtils.collectionToCommaDelimitedString(this.annotatedClasses)+"]");}
reader.register(this.annotatedClasses.toArray(newClass<?>[this.annotatedClasses.size()]));}if(!this.basePackages.isEmpty()){if(logger.isInfoEnabled()){
logger.info("Scanning base packages: ["+StringUtils.collectionToCommaDelimitedString(this.basePackages)+"]");}
scanner.scan(this.basePackages.toArray(newString[this.basePackages.size()]));}//获取容器定义的Bean定义资源路径String[] configLocations =getConfigLocations();//如果定位的Bean定义资源路径不为空if(configLocations !=null){for(String configLocation : configLocations){try{//使用当前容器的类加载器加载定位路径的字节码类文件Class<?> clazz =ClassUtils.forName(configLocation,getClassLoader());if(logger.isInfoEnabled()){
logger.info("Successfully resolved class for ["+ configLocation +"]");}
reader.register(clazz);}catch(ClassNotFoundException ex){if(logger.isDebugEnabled()){
logger.debug("Could not load class for config location ["+ configLocation +"] - trying package scan. "+ ex);}//如果容器类加载器加载定义路径的Bean定义资源失败//则启用容器类路径扫描器扫描给定路径包及其子包中的类int count = scanner.scan(configLocation);if(logger.isInfoEnabled()){if(count ==0){
logger.info("No annotated classes found for specified class/package ["+ configLocation +"]");}else{
logger.info("Found "+ count +" annotated classes in package ["+ configLocation +"]");}}}}}}