Spring Bean定义的加载解析过程之注解的过程

追风赶月莫停留,平芜尽处是春山。这篇文章主要讲述Spring Bean定义的加载解析过程之注解的过程相关的知识,希望能为你提供帮助。
@TOC
注解的使用

public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext( "edu.demo.spring.bean","edu.demo.spring.ext"); Boy boy = context.getBean(Lad.class); boy.sayLove(); }

上面是示例代码,主要的步骤如下图:
Spring Bean定义的加载解析过程之注解的过程

文章图片

要进行debug分析的话,需要在DefaultListableBeanFactory类下,registerBeanDefinition方法中打断点进行调试分析。
注解的加载处理下图是具体的调用栈信息:
Spring Bean定义的加载解析过程之注解的过程

文章图片

第一步:AnnotationConfigApplicationContext
/** * 创建一个AnnotationConfigApplicationContext容器,然后在给定的包下扫描组件 * 把这些组件注册成bean定义信息,并且自动刷新容器 * @param basePackages 扫描组件类的包,可以定义多个 */ public AnnotationConfigApplicationContext(String... basePackages) { this(); scan(basePackages); refresh(); }

/** * 在这个构造函数中,构建了AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner对象 * AnnotatedBeanDefinitionReader用来解读注解信息 * ClassPathBeanDefinitionScanner用来扫描包 */ public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); }

AnnotationConfigApplicationContext类中,主要做的工作,就是在构造函数中构建了AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner对象。
第二步:AnnotatedBeanDefinitionReader
/** * 从给定的Bean定义注册接口中创建一个AnnotatedBeanDefinitionReader * 然后进行初始化AnnotatedBeanDefinitionReader */ public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) { this(registry, getOrCreateEnvironment(registry)); }/** * 从BeanDefinitionRegistry获取Environment * 如果获取不到就返回一个StandardEnvironment */ private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); if (registry instanceof EnvironmentCapable) { return ((EnvironmentCapable) registry).getEnvironment(); } return new StandardEnvironment(); } public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) { //非空判断 Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); Assert.notNull(environment, "Environment must not be null"); this.registry = registry; this.conditionEvaluator = new ConditionEvaluator(registry, environment, null); AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); }

在AnnotatedBeanDefinitionReader类中,主要做的事情,就是初始化AnnotatedBeanDefinitionReader对象。
第三步:AnnotationConfigUtils
/** * 注册所有关于注解配置的处理器,注册到BeanFactory * @param registry the registry to operate on */ public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) { registerAnnotationConfigProcessors(registry, null); } /** * 注册所有关于注解配置的处理器,注册到BeanFactory */ public static Set< BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) {......//将需要使用到的各种处理器注册成bean定义,然后注入到bean工厂中,作为bean来使用 Set< BeanDefinitionHolder> beanDefs = new LinkedHashSet< > (8); //@Configuration注解类后置处理器 if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); }//@Autowired注解类后置处理器 if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); }// 检查是否支持JSR-250 if (jsr250Present & & !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); }// 检查是否支持JPA if (jpaPresent & & !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(); try { def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader())); } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex); } def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)); }if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME)); }if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME)); }return beanDefs; }private static BeanDefinitionHolder registerPostProcessor( BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(beanName, definition); return new BeanDefinitionHolder(definition, beanName); }

通过方法的名字可以知道,这一步主要做的事情,就是注册注解配置的Processor,注册到内部的BeanFactory中,这里的Processor是做什么用的?
在注解的加载过程中,除了加载注册自己的Bean以外,Spring内部也有各种bean注入到工厂中,用来处理各种逻辑,比如上面代码中的,注解bean定义的相关处理对象,都是通过bean定义注入到工厂中的。
第四步:
@Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {this.beanFactory.registerBeanDefinition(beanName, beanDefinition); }

向BeanFactory中注册注册处理器的Bean定义信息。
从上面的调用栈来看,这里并没有注册我们自己定义的Bean定义信息,而是一些Processor。而且也没有看到它做扫描包的工作。
从第一步的代码看到,这里还只是在AnnotationConfigApplicationContext的构造函数中,第二步才执行scan方法,第三步才是refresh方法。注解的方式是在构造函数中就进行了各种初始化的准备,而XML的方式是在refresh方法中就进行了Bean定义的注册。
registerAnnotationConfigProcessors,从方法名上来理解,就是注册了一些注解配置的处理器,下面从ConfigurationClassPostProcessor入手来看下,这些Processor具体是用来干什么的。
/** * {@link BeanFactoryPostProcessor} used for bootstrapping processing of * {@link Configuration @Configuration} classes. * * < p> Registered by default when using {@code < context:annotation-config/> } or * {@code < context:component-scan/> }. Otherwise, may be declared manually as * with any other BeanFactoryPostProcessor. * * < p> This post processor is priority-ordered as it is important that any * {@link Bean} methods declared in {@code @Configuration} classes have * their corresponding bean definitions registered before any other * {@link BeanFactoryPostProcessor} executes. * * @author Chris Beams * @author Juergen Hoeller * @author Phillip Webb * @since 3.0 */ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware { }

通过注释可以看到,这是在启动阶段用来处理@Configuration注解的BeanFactoryPostProcessor,但是这里并没有看到BeanFactoryPostProcessor,但是有一个接口BeanDefinitionRegistryPostProcessor,点进去可以看到,它的父级就是BeanFactoryPostProcessor。
ConfigurationClassPostProcessor的继承体系如下:
Spring Bean定义的加载解析过程之注解的过程

文章图片

下面来看下BeanDefinitionRegistryPostProcessor:
/** * Extension to the standard {@link BeanFactoryPostProcessor} SPI, allowing for * the registration of further bean definitions < i> before< /i> regular * BeanFactoryPostProcessor detection kicks in. In particular, * BeanDefinitionRegistryPostProcessor may register further bean definitions * which in turn define BeanFactoryPostProcessor instances. * * @author Juergen Hoeller * @since 3.0.1 * @see org.springframework.context.annotation.ConfigurationClassPostProcessor */ public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {/** * Modify the application context\'s internal bean definition registry after its * standard initialization. All regular bean definitions will have been loaded, * but no beans will have been instantiated yet. This allows for adding further * bean definitions before the next post-processing phase kicks in. * @param registry the bean definition registry used by the application context * @throws org.springframework.beans.BeansException in case of errors */ void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException; }

BeanDefinitionRegistryPostProcessor扩展了BeanFactoryPostProcessor,增加了
BeanDefinitionRegistry位置的处理,即它可以提前对注册好的BeanDefinitionRegistry进行前置处理
Spring Bean定义的加载解析过程之注解的过程

文章图片

从上图可以看到,在bean的构建过程中,箭头所指向的地方,都可以进行扩展,所以不难看出BeanDefinitionRegistryPostProcessor的作用
再来看下BeanFactoryPostProcessor:
@FunctionalInterface public interface BeanFactoryPostProcessor {/** * Modify the application context\'s internal bean factory after its standard * initialization. All bean definitions will have been loaded, but no beans * will have been instantiated yet. This allows for overriding or adding * properties even to eager-initializing beans. * @param beanFactory the bean factory used by the application context * @throws org.springframework.beans.BeansException in case of errors */ void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException; }

从上面的注释信息,可以知道,这里所做的事情就是,在所有的bean定义加载完成,但是还没有进行实例化之前,对BeanFactory中的bean定义信息可以进行一些想要做的处理。
Spring Bean定义的加载解析过程之注解的过程

文章图片

这是Spring提供的扩展点之一,在BeanFactory开始创建bean实例之前,对beanFactory中的bean定义信息进行一些处理
装载外部的配置文件:
< bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" > < property name="locations" value="https://www.songbingjia.com/android/classpath:application.properties"/> < /bean>

下面是简单实现的例子:
@Component public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println(this + "BeanFactoryPostProcessor工作了.................................."); } }

在测试类里面,增加上面类所在包的扫描:
ApplicationContext context = new AnnotationConfigApplicationContext( "edu.demo.spring");

下面是它的调用栈:
Spring Bean定义的加载解析过程之注解的过程

文章图片

在PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors创建并执行的这个MyBeanFactoryPostProcessor。
【Spring Bean定义的加载解析过程之注解的过程】输出如下:
Spring Bean定义的加载解析过程之注解的过程

文章图片

IOC容器与BeanFactoryPostProcessor的关系
Spring Bean定义的加载解析过程之注解的过程

文章图片

注解的扫描过程
Spring Bean定义的加载解析过程之注解的过程

文章图片

在上图的位置设置断点,然后释放,最后到DefaultListableBeanFactory.registerBeanDefinition断点可以得到调用栈。
Spring Bean定义的加载解析过程之注解的过程

文章图片

第一步:
/** * 在指定的包内执行扫描操作 * < p> Note that {@link #refresh()} must be called in order for the context * to fully process the new classes. * @param basePackages the packages to scan for component classes * @see #register(Class...) * @see #refresh() */ @Override public void scan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); this.scanner.scan(basePackages); }

/** * 在指定的包内执行扫描操作 * 构建并初始化ClassPathBeanDefinitionScanner扫描器对象,开始进行扫描 * @param basePackages the packages to check for annotated classes * @return number of beans registered */ public int scan(String... basePackages) { //获取扫描到的bean定义的个数 int beanCountAtScanStart = this.registry.getBeanDefinitionCount(); doScan(basePackages); // Register annotation config processors, if necessary. if (this.includeAnnotationConfig) { AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); }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}) */ protected Set< BeanDefinitionHolder> doScan(String... basePackages) { }

完成包名下的bean定义的扫描,并且返回注册的bean定义集合。
第三步:
// 完成bean定义到bean工厂的注册 registerBeanDefinition(String, BeanDefinition):929, DefaultListableBeanFactory(org.springframework.beans.factory.support)registerBeanDefinition(String, BeanDefinition):323, GenericApplicationContext(org.springframework.context.support)registerBeanDefinition(BeanDefinitionHolder, BeanDefinitionRegistry):164,BeanDefinitionReaderUtils (org.springframework.beans.factory.support)registerBeanDefinition(BeanDefinitionHolder, BeanDefinitionRegistry):320,ClassPathBeanDefinitionScanner (org.springframework.context.annotation)

重点的部分在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) { //找到指定包下的所有候选组件(配置的bean) Set< BeanDefinition> candidates = findCandidateComponents(basePackage); //扫描所有的候选组件 for (BeanDefinition candidate : candidates) { ScopeMetadata scopeMetadata = https://www.songbingjia.com/android/this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); //注册bean定义到BeanFactory中 registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }

进入findCandidateComponents方法:
/** * 扫描指定的路径,获取候选组件 * @param basePackage the package to check for annotated classes * @return a corresponding Set of autodetected bean definitions */ public Set< BeanDefinition> findCandidateComponents(String basePackage) { //如果有组件索引并且索引支持包含的filters,就从组件索引中获取获选组件 if (this.componentsIndex != null & & indexSupportsIncludeFilters()) { return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); } else { // 否则,进行类目录下指定包的扫描 return scanCandidateComponents(basePackage); } }

组件索引请查看官方文档:https://docs.spring.io/spring/docs/5.1.8.RELEASE/spring-framework-reference/core.html#beans-scanning-index
如果要使用组件索引,需要加入下面的maven配置:
< dependencies> < dependency> < groupId> org.springframework< /groupId> < artifactId> spring-context-indexer< /artifactId> < version> 5.1.8.RELEASE< /version> < optional> true< /optional> < /dependency> < /dependencies>

这里没有使用到,所以进入了scanCandidateComponents方法:
private Set< BeanDefinition> scanCandidateComponents(String basePackage) { //所有候选组件的集合 Set< BeanDefinition> candidates = new LinkedHashSet< > (); try { //构建扫描包的路径表达式,类似于切点表达式 //classpath*:edu/demo/spring/ext/**/*.class String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + \'/\' + this.resourcePattern; // ResourcePatternResolver扫描包获取到.class文件 // 扫描的逻辑:在包下找.class文件,这里要求能够灵活指定包,就需要用到模式匹配 // 默认用到的Ant Path模式匹配,如指定的包 edu.demo.**.service 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,元数据读取器,类似xml读取器 MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); if (isCandidateComponent(metadataReader)) { // 最终通过MetadataReader用ScannedGenericBeanDefinition装载了注解bean定义 ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setSource(resource); //必须是一个可以继承的类,不能是接口和封闭类,抽象类必须有Lookup注解 if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } else { // 忽略,不是一个顶层的具体类 if (debugEnabled) { logger.debug("Ignored because not a concrete top-level class: " + resource); } } } else { // 忽略,不能匹配到过滤器 if (traceEnabled) { logger.trace("Ignored because not matching any filter: " + resource); } } } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to read candidate component class: " + resource, ex); } } else { if (traceEnabled) { logger.trace("Ignored because not readable: " + resource); } } } } catch (IOException ex) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); } return candidates; }

进入getResourcePatternResolver方法:
private ResourcePatternResolver getResourcePatternResolver() { if (this.resourcePatternResolver == null) { this.resourcePatternResolver = new PathMatchingResourcePatternResolver(); } return this.resourcePatternResolver; }

PathMatchingResourcePatternResolver类:能将指定的资源位置路径解析为一个或多个匹配的资源。可以是一对一的资源指定,也可以是一对多的匹配模式,通过ant path格式、classpath*:前缀
public class PathMatchingResourcePatternResolver implements ResourcePatternResolver { // ......// 默认采用AntPathMatcher private PathMatcher pathMatcher = new AntPathMatcher(); // ...... }

模式匹配的关系图:
Spring Bean定义的加载解析过程之注解的过程

文章图片

下面看下ScannedGenericBeanDefinition:
public class ScannedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition {private final AnnotationMetadata metadata; /** * Create a new ScannedGenericBeanDefinition for the class that the * given MetadataReader describes. * @param metadataReader the MetadataReader for the scanned target class */ public ScannedGenericBeanDefinition(MetadataReader metadataReader) { Assert.notNull(metadataReader, "MetadataReader must not be null"); this.metadata = https://www.songbingjia.com/android/metadataReader.getAnnotationMetadata(); setBeanClassName(this.metadata.getClassName()); setResource(metadataReader.getResource()); }@Override public final AnnotationMetadata getMetadata() { return this.metadata; }@Override @Nullable public MethodMetadata getFactoryMethodMetadata() { return null; } }

继承自GenericBeanDefinition类,基于ASM Cla***eader的AnnotatedBeanDefinition实现,支持注解元数据。
在这里为什么要使用AnnotatedBeanDefinition而不使用GenericBeanDefinition?
下面看下AnnotatedBeanDefinition接口提供的两个方法:
public interface AnnotatedBeanDefinition extends BeanDefinition {/** * 获取注解的元数据 * Obtain the annotation metadata (as well as basic class metadata) * for this bean definition\'s bean class. * @return the annotation metadata object (never {@code null}) */ AnnotationMetadata getMetadata(); /** * 获取工厂方法的元数据 * Obtain metadata for this bean definition\'s factory method, if any. * @return the factory method metadata, or {@code null} if none * @since 4.1.1 */ @Nullable MethodMetadata getFactoryMethodMetadata(); }

元数据信息Spring中定义了一套方案来描述一个类、一个类上的注解、一个方法等的描述接口,里面定义了一些相关的操作。
比如:
  • 类:类的名称是什么,用了什么修饰符
  • 注解:类上的注解的名字,注解的元注解信息有什么,注解的注释信息是什么,注解里面有哪些属性等
MetadataReader接口:
/** * Simple facade for accessing class metadata, * as read by an ASM {@link org.springframework.asm.Cla***eader}. * 通过ASM的Cla***eader读取类的元信息,提供一个简单的外观模式。 * 1. 用ASM来实现这个功能;2. 这是一个简单的外观模式实现 * * @author Juergen Hoeller * @since 2.5 */ public interface MetadataReader {/** * Return the resource reference for the class file. * 返回类的资源文件 */ Resource getResource(); /** * Read basic class metadata for the underlying class. */ ClassMetadata getClassMetadata(); /** * Read full annotation metadata for the underlying class, * including metadata for annotated methods. * 返回注解的元数据信息 */ AnnotationMetadata getAnnotationMetadata(); }

实现类:SimpleMetadataReader
final class SimpleMetadataReader implements MetadataReader { SimpleMetadataReader(Resource resource, @Nullable ClassLoader classLoader) throws IOException { // 构建注解元数据读取访问者 SimpleAnnotationMetadataReadingVisitor visitor = new SimpleAnnotationMetadataReadingVisitor(classLoader); // 创建资源对应的ASM Cla***eader对象,并且对用visitor对Cla***eader对象进行访问解读 getCla***eader(resource).accept(visitor, PARSING_OPTIONS); // 扫描到的带有注解的类 this.resource = resource; // 获得注解元数据信息 this.annotationMetadata = https://www.songbingjia.com/android/visitor.getMetadata(); } }

ASM是一个低层次的字节码操作库,官网地址:https://asm.ow2.io/
Spring中通过ASM字节码操作库来读取的类信息、注解信息,它们的类关系图如下:
Spring Bean定义的加载解析过程之注解的过程

文章图片

扫描过滤器
/** * Determine whether the given class does not match any exclude filter * and does match at least one include filter. * @param metadataReader the ASM Cla***eader for the class * @return whether the class qualifies as a candidate component */ protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { 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; }

< context:component-scan base-package="edu.demo.spring.web" > < context:exclude-filter type="annotation" expression="@Service"/> < context:include-filter type="annotation" expression="@Controller"/> < /context:component-scan>

filter可以使用上面的方式在xml文件中进行配置,exclude是不包含这些组件,include是需要包含这些组件。
@service @controller等是怎么匹配到的呢,默认情况下的filter是什么样的,看下面的代码:
protected void registerDefaultFilters() { this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try { 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 { 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. } }

AnnotationTypeFilter的父类AbstractTypeHierarchyTraversingFilter#match
(MetadataReader,MetadataReaderFactory)方法,最后会到AnnotationTypeFilter#matchSelf方法:
@Override protected boolean matchSelf(MetadataReader metadataReader) { AnnotationMetadata metadata = https://www.songbingjia.com/android/metadataReader.getAnnotationMetadata(); // 包含指定的注解 或者 注解里面包含指定注解, 比如指定的@Componet注解,在@Service注解中有包含 return metadata.hasAnnotation(this.annotationType.getName()) || (this.considerMetaAnnotations & & metadata.hasMetaAnnotation(this.annotationType.getName())); }

自定义实现TypeFilter:
public class MyTypeFilter implements TypeFilter { @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { // 使用metadataReader中的类信息、注解信息来进行你的过滤判断逻辑 return metadataReader.getClassMetadata().getClassName().equals(Lad.class.getName()); } }

Bean定义的注册
/** * 将给定的bean定义信息注册到bean工厂中 * Register the given bean definition with the given bean factory. * @param definitionHolder the bean definition including name and aliases * @param registry the bean factory to register with * @throws BeanDefinitionStoreException if registration failed */ public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {// Register bean definition under primary name. //获取beanName String beanName = definitionHolder.getBeanName(); //通过bean工厂注册bean定义信息 registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. //把beanName和别名进行绑定,如果存在别名就注册别名进去 String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } } }

核心的部分在DefaultListableBeanFactory#registerBeanDefinition方法中:
@Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {//判断beanName和beanDefinition信息是否为空 Assert.hasText(beanName, "Bean name must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); //如果存在继承自AbstractBeanDefinition的bean定义 //那么就对这个bean进行校验 if (beanDefinition instanceof AbstractBeanDefinition) { try { ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } }//是否已经存在相关的bean定义了 BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); //bean定义已经存在的情况下 if (existingDefinition != null) { //如果不允许重写覆盖,则抛出异常 if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } //运行重写覆盖的处理,进行一些日志信息的打印,告知处理的信息 else if (existingDefinition.getRole() < beanDefinition.getRole()) { // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE if (logger.isInfoEnabled()) { logger.info("Overriding user-defined bean definition for bean \'" + beanName + "\' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } else if (!beanDefinition.equals(existingDefinition)) { if (logger.isDebugEnabled()) { logger.debug("Overriding bean definition for bean \'" + beanName + "\' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } else { if (logger.isTraceEnabled()) { logger.trace("Overriding bean definition for bean \'" + beanName + "\' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } //覆盖原有的bean定义信息 this.beanDefinitionMap.put(beanName, beanDefinition); } //beanName的bean定义不存在的情况 else { //当前的bean对象是否正在创建 if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) //启动期间,同步处理,防止其他地方集合的迭代异常 synchronized (this.beanDefinitionMap) { //使用ConcurrentHashMap进行存储 this.beanDefinitionMap.put(beanName, beanDefinition); List< String> updatedDefinitions = new ArrayList< > (this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; removeManualSingletonName(beanName); } } else { // Still in startup registration phase //当前bean还没有开始创建,直接put this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionNames.add(beanName); removeManualSingletonName(beanName); } this.frozenBeanDefinitionNames = null; }//如果对应的单例bean存在,则重置这个Bean if (existingDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } // 需要冻结配置,清除类型映射缓存 else if (isConfigurationFrozen()) { clearByTypeCache(); } }

别名的处理,将别名作为Key,beanName作为Value进行map存储
@Override public void registerAlias(String name, String alias) { Assert.hasText(name, "\'name\' must not be empty"); Assert.hasText(alias, "\'alias\' must not be empty"); synchronized (this.aliasMap) { if (alias.equals(name)) { this.aliasMap.remove(alias); if (logger.isDebugEnabled()) { logger.debug("Alias definition \'" + alias + "\' ignored since it points to same name"); } } else { String registeredName = this.aliasMap.get(alias); if (registeredName != null) { if (registeredName.equals(name)) { // An existing alias - no need to re-register return; } if (!allowAliasOverriding()) { throw new IllegalStateException("Cannot define alias \'" + alias + "\' for name \'" + name + "\': It is already registered for name \'" + registeredName + "\'."); } if (logger.isDebugEnabled()) { logger.debug("Overriding alias \'" + alias + "\' definition for registered name \'" + registeredName + "\' with new target name \'" + name + "\'"); } } checkForAliasCircle(name, alias); this.aliasMap.put(alias, name); if (logger.isTraceEnabled()) { logger.trace("Alias definition \'" + alias + "\' registered for name \'" + name + "\'"); } } } }


    推荐阅读