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

本文内容纲要:

- 注解的使用

- 注解的加载处理

- IOC容器与BeanFactoryPostProcessor的关系

- 注解的扫描过程

- 元数据信息

- 扫描过滤器

- Bean定义的注册

注解的使用

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();

}

上面是示例代码,主要的步骤如下图:

要进行debug分析的话,需要在DefaultListableBeanFactory类下,registerBeanDefinition方法中打断点进行调试分析。

注解的加载处理

下图是具体的调用栈信息:

第一步: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的继承体系如下:

下面来看下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进行前置处理

从上图可以看到,在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提供的扩展点之一,在BeanFactory开始创建bean实例之前,对beanFactory中的bean定义信息进行一些处理

装载外部的配置文件:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >

<property name="locations" value="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");

下面是它的调用栈:

在PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors创建并执行的这个MyBeanFactoryPostProcessor。

输出如下:

IOC容器与BeanFactoryPostProcessor的关系

注解的扫描过程


在上图的位置设置断点,然后释放,最后到DefaultListableBeanFactory.registerBeanDefinition断点可以得到调用栈。

第一步:

/**

* 在指定的包内执行扫描操作

* <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 = 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();

// ......

}

模式匹配的关系图:


下面看下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 = 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 ClassReader的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.ClassReader}.

* 通过ASM的ClassReader读取类的元信息,提供一个简单的外观模式。

* 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 ClassReader对象,并且对用visitor对ClassReader对象进行访问解读

getClassReader(resource).accept(visitor, PARSING_OPTIONS);

// 扫描到的带有注解的类

this.resource = resource;

// 获得注解元数据信息

this.annotationMetadata = visitor.getMetadata();

}

}

ASM是一个低层次的字节码操作库,官网地址:https://asm.ow2.io/

Spring中通过ASM字节码操作库来读取的类信息、注解信息,它们的类关系图如下:

扫描过滤器

/**

* 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

*/

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 = 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 + "'");

}

}

}

}

本文内容总结:注解的使用,注解的加载处理,IOC容器与BeanFactoryPostProcessor的关系,注解的扫描过程,元数据信息,扫描过滤器,Bean定义的注册,

原文链接:https://www.cnblogs.com/fox2said/p/15147818.html

以上是 Spring Bean定义的加载解析过程之注解的过程 的全部内容, 来源链接: utcz.com/z/362382.html

回到顶部