Spring Bean定义的加载解析过程之注解的过程
Posted 狐言不胡言
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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();
}
上面是示例代码,主要的步骤如下图:
要进行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 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 = 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 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 = 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 + "\'");
}
}
}
}
以上是关于Spring Bean定义的加载解析过程之注解的过程的主要内容,如果未能解决你的问题,请参考以下文章
Spring源码--03--加载bean的定义信息---Spring注解解析原理