BlazeMaple BlazeMaple
首页
  • 基础知识

    • Java的基本数据类型
    • Java中的常用类String
    • Java中的异常
    • Java中的注解
    • Java中的反射机制
    • Java中的泛型
    • Java为什么是值传递
  • 集合框架

    • Java集合核心知识总结
    • HashMap的7种遍历方式
    • 源码分析
  • Java新特性

    • Java8新特性
  • IO流

    • Java基础IO总结
    • Java IO中的设计模式
    • Java IO模型
    • IO多路复用详解
  • 并发编程

    • 并发编程基础总结
  • JVM

    • JVM基础总结
  • MySQL

    • MySQL核心知识小结
    • MySQL 45讲
  • Redis

    • Redis核心入门知识简记
  • Spring
  • SpringCloud Alibaba
  • 开发工具

    • Git详解
    • Maven详解
    • Docker详解
    • Linux常用命令
  • 在线工具

    • json (opens new window)
    • base64编解码 (opens new window)
    • 时间戳转换 (opens new window)
    • unicode转换 (opens new window)
    • 正则表达式 (opens new window)
    • md5加密 (opens new window)
    • 二维码 (opens new window)
    • 文本比对 (opens new window)
  • 学习资源

    • 计算机经典电子书PDF
    • hot120
GitHub (opens new window)
首页
  • 基础知识

    • Java的基本数据类型
    • Java中的常用类String
    • Java中的异常
    • Java中的注解
    • Java中的反射机制
    • Java中的泛型
    • Java为什么是值传递
  • 集合框架

    • Java集合核心知识总结
    • HashMap的7种遍历方式
    • 源码分析
  • Java新特性

    • Java8新特性
  • IO流

    • Java基础IO总结
    • Java IO中的设计模式
    • Java IO模型
    • IO多路复用详解
  • 并发编程

    • 并发编程基础总结
  • JVM

    • JVM基础总结
  • MySQL

    • MySQL核心知识小结
    • MySQL 45讲
  • Redis

    • Redis核心入门知识简记
  • Spring
  • SpringCloud Alibaba
  • 开发工具

    • Git详解
    • Maven详解
    • Docker详解
    • Linux常用命令
  • 在线工具

    • json (opens new window)
    • base64编解码 (opens new window)
    • 时间戳转换 (opens new window)
    • unicode转换 (opens new window)
    • 正则表达式 (opens new window)
    • md5加密 (opens new window)
    • 二维码 (opens new window)
    • 文本比对 (opens new window)
  • 学习资源

    • 计算机经典电子书PDF
    • hot120
GitHub (opens new window)
  • Spring

    • Spring源码解析
    • Spring6源码
      • 1.1 @Configuration注解
        • 注解源码
        • 源码时序图
        • 注册ConfigurationClassPostProcessor流程源码时序图
        • 注册配置类流程源码时序图
        • 实例化流程源码时序图
        • 源码解析
        • 注册ConfigurationClassPostProcessor流程源码解析
        • 注册配置类流程源码解析
        • 实例化流程源码解析
        • 思考
        • 1. Spring为何在创建IOC容器时先注册ConfigurationClassPostProcessor类后置处理器的Bean定义信息,随后才是注册标注了@Configuration注解的ConfigurationAnnotationConfig配置类的Bean定义信息?
        • 2. Spring为何先将类的Bean定义信息注册到IOC容器?为何不是直接注册实例化后的对象?
        • 3. Spring为何是在刷新IOC容器时,实例化标注了@Configuration注解的配置类的代理对象?为何不是在创建IOC容器时就进行实例化?
      • 1.2 @ComponentScans与@ComponentScan注解
        • 注解源码
        • 源码时序图
        • 源码解析
        • 思考
        • 1.Spring扫描指定包的逻辑为何复杂?
        • 2.配置类上不标注@ComponentScans或@ComponentScan能扫描到哪些包下的类?
        • 3.@ComponentScan注解中的basePackages或value属性可以设置任意包名吗?
      • 1.3 @Bean注解
        • 注解源码
        • 源码时序图
        • 注册Bean的流程
        • 调用初始化方法
        • 调用销毁方法
        • 源码解析
        • 注册bean的流程
        • 调用初始化方法
        • 调用销毁方法
        • 思考
        • 1. @Bean注解为何也是先将Bean定义信息注册到IOC容器中呢?这样做的好处是什么?
        • 2. @Bean注解标注的方法被Spring解析后将Bean定义信息注册到IOC容器中后,何时会对注册的信息进行实例化呢?实例化的流程是怎样的?
        • 3. Spring是如何调用@Bean注解中使用initMethod和destroyMethod属性指定的方法的?调用的流程是怎样的呢?
      • 1.4 从IOC容器中获取Bean的过程
        • 源码时序图
        • 源码解析
        • 思考
        • 1.Spring为何会有循环依赖的问题?
        • 2.Spring如何解决循环依赖问题?
        • 3.Spring为何使用三级缓存解决循环依赖问题?使用二级缓存不行吗?为什么?
      • 1.5 @Import注解
        • 注解源码
        • 源码时序图
        • 源码解析
        • 思考
        • 1. 在ConfigurationClassParser类的processImports()中,如果@Import注解引入的是普通类或者引入的是实现了ImportSelector接口,并且没有实现DeferredImportSelector接口的类,最终还是会执行processImports()方法的else逻辑。那么最终是如何执行else逻辑的?
        • 2. @Import注解的三种案例在Spring底层的源码执行流程分别是什么?
        • 3. 使用@Import注解向IOC容器中注入Bean与使用@Bean注解有什么区别?
      • 1.6 @PropertySource注解
        • 注解源码
        • 源码时序图
        • 源码解析
        • 思考
        • 1. @PropertySource注解的执行流程
        • 2. @PropertySource注解是如何将配置文件加载到环境变量的?
        • 3. @PropertySource注解的使用场景
      • 1.7 @DependsOn注解
        • 注解源码
        • 注解使用场景
        • 源码时序图
        • 注册Bean的源码时序图
        • 调用Bean工厂后置处理器的源码时序图
        • 创建Bean的源码时序图
        • 源码解析
        • 注册Bean的源码流程
        • 调用Bean工厂后置处理器的源码流程
        • 创建Bean的源码流程
        • 思考
        • 1. @DependsOn注解的作用
        • 2. Bean的循环依赖与@DependsOn注解的关系
      • 1.8 @Conditional注解
        • 注解源码
        • 源码时序图
        • 源码解读
        • 扩展注解
        • 思考
        • 1. @Conditional注解的作用是什么?
        • 2. @Conditional注解有哪些使用场景?
        • 3. @Conditional注解与@Profile注解有什么区别?
        • 4. @Conditional注解在Spring内层的执行流程?
      • 1.9 @Lazy注解
        • 注解源码
        • 源码时序图
        • 注册Bean的源码时序图
        • 调用Bean后置处理器的源码时序图
        • 创建单例Bean的源码时序图
        • 源码解析
        • 注册Bean的源码流程
        • 调用Bean后置处理器的源码流程
        • 创建单例Bean的源码流程
        • 思考
        • 1. @Lazy注解的作用是什么?
        • 2. @Lazy注解有哪些使用场景?
        • 3. @Lazy注解延迟创建Bean是如何实现的?
        • 4. @Lazy注解在Spring内部的执行流程?
      • 1.10 @Component注解
        • 注解源码
        • 源码时序图
        • 源码解析
        • 思考
        • 1. @Component注解的作用
        • 2. @Component注解的使用场景
        • 3. @Component注解是如何将Bean注入到IOC容器的
        • 4. @Component注解在Spring内部的执行流程
      • 1.11 @Value注解
        • 注解源码
        • 源码时序图
        • 解析并获取@Value修饰的属性
        • 为@Value修饰的属性赋值
        • 使用@Value获取属性的值
        • 源码解析
        • 解析并获取@Value修饰的属性
        • 为@Value修饰的属性赋值
        • 使用@Value获取属性的值
        • 思考
        • 1. @Value注解的作用
        • 2. @Value注解的使用场景
        • 3. @Value向Bean的字段和方法注入值是如何实现的
        • 4. @Value注解在Spring内部的执行流程
        • 5. @Value注解在Spring源码中的执行流程与@Autowired注解的区别
      • 1.12 @Autowired注解
        • 注解源码
        • 源码时序图
        • 源码解析
        • 思考
        • 1. @Autowired注解的使用场景
        • 2. @Autowired向Bean的字段和方法注入值的实现方式
        • 3. @Autowired注解在Spring内部的执行流程
      • 1.13 @Qualifier注解
        • 注解源码
        • 源码解析
      • 1.14 @Resource注解
        • 注解源码
        • 源码时序图
        • 解析并获取@Resource修饰的属性
        • 为@Resource修饰属性赋值
        • 源码解析
        • 解析并获取@Resource修饰的属性
        • 为@Resource修饰属性赋值
        • 思考
        • 1. @Resource注解的使用场景
        • 2. @Resource向Bean的字段和方法注入值的实现
        • 3. @Resource与@Autowired的区别
      • 1.15 @Scope注解
        • 注解源码
        • 源码时序图
        • 注册Bean的流程
        • 调用Bean工厂后置处理器
        • 获取Bean的流程
        • 源码解析
        • 注册Bean的流程
        • 调用Bean工厂后置处理器
        • 获取Bean的流程
        • 思考
        • 1. @Scope注解的使用场景
        • 2. @Scope注解在Spring内部的执行流程
        • 3. @Scope是如何创建代理类的
      • 1.16 @PostConstruct注解与@PreDestroy注解
        • 注解源码
        • 源码时序图
        • @PostConstruct源码时序图
        • @PreDestroy源码时序图
        • 源码解析
        • @PostConstruct源码解析
        • @PreDestroy源码解析
        • 思考
      • 2.1 @EnableAspectJAutoProxy注解
        • 注解源码
        • 源码时序图
        • 注册AnnotationAwareAspectJAutoProxyCreator类
        • 解析AnnotationAwareAspectJAutoProxyCreator类
        • 源码解析
        • 注册AnnotationAwareAspectJAutoProxyCreator类
        • 解析AnnotationAwareAspectJAutoProxyCreator类
        • 思考
        • 1. @EnableAspectJAutoProxy注解在Spring底层的执行流程
        • 2. @EnableAspectJAutoProxy注解都做了哪些工作
        • 3. @EnableAspectJAutoProxy注解是如何开启AOP代理的
      • 2.2 切入点表达式
        • 源码时序图
        • 源码解析
  • SpringCloud Alibaba

    • SpringCloud Alibaba核心知识
    • SpringCloud Alibaba实战
  • 常用框架
  • Spring
BlazeMaple
2024-08-05
目录

Spring6源码

# 一. IOC容器

# 1.1 @Configuration注解

@Configuration注解是从Spring 3.0版本开始加入的一个使Spring能够支持注解驱动开发的标注型注解,主要用于标注在类上。当某个类标注了@Configuration注解时,表示这个类是Spring的一个配置类。@Configuration注解能够替代Spring的applicationContext.xml文件,并且被@Configuration注解标注的类,能够自动注册到IOC容器并进行实例化。

# 注解源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
	@AliasFor(annotation = Component.class)
	String value() default "";
//Since: 5.2
	boolean proxyBeanMethods() default true;
//Since: 6.0
	boolean enforceUniqueMethods() default true;
}
1
2
3
4
5
6
7
8
9
10
11
12

@Configuration注解中每个属性的含义如下所示。

  • value:存入到Spring IOC容器中的Bean的id。
  • proxyBeanMethods:表示被@Configuration注解标注的配置类是否会被代理,并且在配置类中使用@Bean注解生成的Bean对象在IOC容器中是否是单例对象,取值为true或者false。当取值为true时,表示full(全局)模式,此模式下被@Configuration注解标注的配置类会被代理,在配置类中使用@Bean注解注入到IOC容器中的Bean对象是单例模式,无论调用多少次被@Bean注解标注的方法,返回的都是同一个Bean对象。当取值为false时,表示lite(轻量级)模式,此模式下被@Configuration注解标注的配置类不会被代理,在配置类中使用@Bean注解注入到IOC容器中的Bean对象不是单例模式,每次调用被@Bean注解标注的方法时,都会返回一个新的Bean对象。默认的取值为true。
  • enforceUniqueMethods:指定使用@Bean注解标注的方法是否需要具有唯一的方法名称,取值为true或者false。当取值为true时,表示使用@Bean注解标注的方法具有唯一的方法名称,并且这些方法名称不会重叠。当取值为false时,表示使用@Bean注解标注的方法名称不唯一,存在被重叠的风险。默认取值为true。

@Configuration注解本质上是一个@Component注解,所以被@Configuration注解标注的配置类本身也会被注册到IOC容器中。同时,@Configuration注解也会被@ComponentScan注解扫描到。

# 源码时序图

@Configuration注解在源码层面的执行流程涉及到注册与实例化两种执行流程。

  • 注册流程:涉及到Spring内部的ConfigurationClassPostProcessor类的Bean定义信息的注册,以及标注了@Configuration注解的Config配置类的Bean定义信息注册。
  • 实例化流程:Spring IOC容器在启动过程中,最终会调用AnnotationConfigApplicationContext类的refresh()方法刷新IOC容器,刷新IOC容器的过程中就会对标注了@Configuration注解的配置类进行实例化。

# 注册ConfigurationClassPostProcessor流程源码时序图

ConfigurationClassPostProcessor后置处理器是解析@Configuration注解的核心类,Spring IOC容器启动时,会向IOC容器中注册ConfigurationClassPostProcessor类的Bean定义信息。

图1-1

# 注册配置类流程源码时序图

在配置类上标注了@Configuration注解,当Spring IOC容器启动时,也会将配置类的Bean定义信息注册到Spring IOC容器中

图1-2

Spring IOC容器在启动时,会向IOC容器中注册ConfigurationClassPostProcessor类的bean定义信息和使用@Configuration注解标注的配置类的Bean定义信息。当Spring IOC容器再刷新时,会递归处理所有使用@Configuration注解标注的类,解析@Bean等注解标注的方法,解析成一个个ConfigurationClassBeanDefinition类型的BeanDefinition对象,注册到IOC容器中。

# 实例化流程源码时序图

Spring IOC容器在启动过程中,最终会调用AnnotationConfigApplicationContext类的refresh()方法刷新IOC容器,刷新IOC容器的过程中就会对标注了@Configuration注解的配置类进行实例化。

图1-3-1

图1-3-2

# 源码解析

# 注册ConfigurationClassPostProcessor流程源码解析

(1)运行案例程序启动类ConfigurationAnnotationTest的main()方法

public class ConfigurationAnnotationTest {

private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationAnnotationTest.class);

public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigurationAnnotationConfig.class);
ConfigurationAnnotationConfig config = context.getBean(ConfigurationAnnotationConfig.class);
Person person1 = config.person();
Person person2 = config.person();
LOGGER.info("person1 是否等于 person2 ===>> {}", (person1 == person2));
}
}
1
2
3
4
5
6
7
8
9
10
11
12

在main()方法中会调用AnnotationConfigApplicationContext类的构造方法传入配置类ConfigurationAnnotationConfig的Class对象来创建IOC容器。接下来,会进入AnnotationConfigApplicationContext类的构造方法。

(2)解析AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class<?>... componentClasses)构造方法

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
1
2
3
4
5

上述构造方法中,会通过this()调用AnnotationConfigApplicationContext类的无参构造方法。

(3)解析AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext()无参构造方法

public AnnotationConfigApplicationContext() {
StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
this.reader = new AnnotatedBeanDefinitionReader(this);
createAnnotatedBeanDefReader.end();
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
1
2
3
4
5
6

在AnnotationConfigApplicationContext类的无参构造方法中,主要的逻辑就是实例化了AnnotatedBeanDefinitionReader类型的reader成员变量和ClassPathBeanDefinitionScanner类型的scanner成员变量。

  • reader:表示注解类型的Bean定义信息读取器,主要就是读取通过注解方式进行实例化的Bean的定义信息。
  • scanner:表示类路径下的Bean定义扫描器,主要就是扫描类路径下的Bean定义信息。

接下来会调用AnnotatedBeanDefinitionReader类中的AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry)构造方法。

(4)解析AnnotatedBeanDefinitionReader类中的AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry)构造方法

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
1
2
3

在上述构造方法中,通过this调用了AnnotatedBeanDefinitionReader类的AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment)构造方法。

(5)解析AnnotatedBeanDefinitionReader类的AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment)构造方法

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);
}
1
2
3
4
5
6
7

在上述构造方法中,最核心的逻辑就是调用了AnnotationConfigUtils工具类的registerAnnotationConfigProcessors()方法,将BeanDefinitionRegistry类型的registry对象传入方法中。registry对象本质上就是一个AnnotationConfigApplicationContext类对象的实例,因为AnnotationConfigApplicationContext类继承了GenericApplicationContext类,而GenericApplicationContext类实现了BeanDefinitionRegistry接口。

(6)解析AnnotationConfigUtils类的registerAnnotationConfigProcessors(BeanDefinitionRegistry registry)方法

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, null);
}
1
2
3

(7)解析AnnotationConfigUtils类的registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, Object source)方法

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {

// 获取默认的ListableBeanFactory
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
// 如果依赖比较器不是AnnotationAwareOrderComparator的实例,则设置依赖比较器为AnnotationAwareOrderComparator
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
// 如果自动装配候选解析器不是ContextAnnotationAutowireCandidateResolver的实例,则设置自动装配候选解析器为新的ContextAnnotationAutowireCandidateResolver
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}

// 创建一个LinkedHashSet来存储bean定义
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

// 如果注册表中不存在CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME的bean定义
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// 创建一个新的RootBeanDefinition实例,并设置其类为ConfigurationClassPostProcessor
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
// 设置bean定义的源为传入的source
def.setSource(source);
// 注册后处理器,并将返回的BeanDefinitionHolder添加到beanDefs集合中
beanDefs.add(registerPostProcessor(registry, def,CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}

// 如果注册表中不存在AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME的bean定义
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// 创建一个新的RootBeanDefinition实例,并设置其类为AutowiredAnnotationBeanPostProcessor
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
// 设置bean定义的源为传入的source
def.setSource(source);
// 注册后处理器,并将返回的BeanDefinitionHolder添加到beanDefs集合中
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}

// 检查是否存在Jakarta Annotations支持,如果存在则添加CommonAnnotationBeanPostProcessor
// Check for Jakarta Annotations support, and if present add the CommonAnnotationBeanPostProcessor.
if (jakartaAnnotationsPresent && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// 创建一个新的RootBeanDefinition实例,并设置其类为CommonAnnotationBeanPostProcessor
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
// 设置bean定义的源为传入的source
def.setSource(source);
// 注册后处理器,并将返回的BeanDefinitionHolder添加到beanDefs集合中
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}

// 检查是否支持JSR-250,如果支持则添加InitDestroyAnnotationBeanPostProcessor用于javax的PostConstruct/PreDestroy注解
if (jsr250Present && !registry.containsBeanDefinition(JSR250_ANNOTATION_PROCESSOR_BEAN_NAME)) {
try {
// 创建InitDestroyAnnotationBeanPostProcessor的RootBeanDefinition
RootBeanDefinition def = new RootBeanDefinition(InitDestroyAnnotationBeanPostProcessor.class);
// 添加initAnnotationType属性,值为javax.annotation.PostConstruct的Class对象
def.getPropertyValues().add("initAnnotationType", classLoader.loadClass("javax.annotation.PostConstruct"));
// 添加destroyAnnotationType属性,值为javax.annotation.PreDestroy的Class对象
def.getPropertyValues().add("destroyAnnotationType", classLoader.loadClass("javax.annotation.PreDestroy"));
// 设置bean定义的源为传入的source
def.setSource(source);
// 注册后处理器,并将返回的BeanDefinitionHolder添加到beanDefs集合中
beanDefs.add(registerPostProcessor(registry, def, JSR250_ANNOTATION_PROCESSOR_BEAN_NAME));
}
catch (ClassNotFoundException ex) {
// 加载javax注解类型的类失败,忽略异常
// Failed to load javax variants of the annotation types -> ignore.
}
}

// 检查是否支持JPA,如果支持则添加PersistenceAnnotationBeanPostProcessor
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// 创建RootBeanDefinition
RootBeanDefinition def = new RootBeanDefinition();
try {
// 设置bean的类为PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME指定的类
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);
}
// 设置bean定义的源为传入的source
def.setSource(source);
// 注册后处理器,并将返回的BeanDefinitionHolder添加到beanDefs集合中
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}

// 如果注册表中不存在EVENT_LISTENER_PROCESSOR_BEAN_NAME的bean定义
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
// 创建EventListenerMethodProcessor的RootBeanDefinition
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
// 设置bean定义的源为传入的source
def.setSource(source);
// 注册后处理器,并将返回的BeanDefinitionHolder添加到beanDefs集合中
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}

// 如果注册表中不存在EVENT_LISTENER_FACTORY_BEAN_NAME的bean定义
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
// 创建DefaultEventListenerFactory的RootBeanDefinition
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
// 设置bean定义的源为传入的source
def.setSource(source);
// 注册后处理器,并将返回的BeanDefinitionHolder添加到beanDefs集合中
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}

// 返回beanDefs集合
return beanDefs;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

其中将@Configuration注解涉及到的ConfigurationClassPostProcessor类的Bean定义信息注册到IOC容器中的核心代码为:

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {
//################省略其他代码########################
// 如果注册表中不存在CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME的bean定义
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// 创建一个新的RootBeanDefinition实例,并设置其类为ConfigurationClassPostProcessor
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
// 设置bean定义的源为传入的source
def.setSource(source);
// 注册后处理器,并将返回的BeanDefinitionHolder添加到beanDefs集合中
beanDefs.add(registerPostProcessor(registry, def,CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//################省略其他代码########################
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

(8)解析registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName)方法

private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
1
2
3
4
5
6

上述代码调用了registry参数的registerBeanDefinition()方法来注册ConfigurationClassPostProcessor类的Bean定义信息,definition参数本质上就是一个AnnotationConfigApplicationContext类的实例对象。最终会调用DefaultListableBeanFactory类的registerBeanDefinition()方法来注册ConfigurationClassPostProcessor类的Bean定义信息。

(9)解析DefaultListableBeanFactory类的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {

// 断言beanName非空
Assert.hasText(beanName, "Bean name must not be empty");
// 断言beanDefinition非空
Assert.notNull(beanDefinition, "BeanDefinition must not be null");

// 判断beanDefinition是否是AbstractBeanDefinition的实例
if (beanDefinition instanceof AbstractBeanDefinition abd) {
try {
// 验证bean定义
abd.validate();
}
catch (BeanDefinitionValidationException ex) {
// 抛出BeanDefinitionStoreException异常,包含bean定义资源描述、beanName以及异常信息
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
   "Validation of bean definition failed", ex);
}
}

// 获取beanName对应的BeanDefinition
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);

if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
// 如果不允许覆盖Bean定义,则抛出异常
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// 如果现有Bean定义的角色小于新Bean定义的角色,则进行覆盖
// 例如,之前是ROLE_APPLICATION,现在用ROLE_SUPPORT或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)) {
// 如果新Bean定义与现有Bean定义不相等,则进行覆盖
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
 "' with a different definition: replacing [" + existingDefinition +
 "] with [" + beanDefinition + "]");
}
}
else {
// 如果新Bean定义与现有Bean定义相等,则进行覆盖(尽管它们相等,但可能由于其他原因需要覆盖)
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
 "' with an equivalent definition: replacing [" + existingDefinition +
 "] with [" + beanDefinition + "]");
}
}
// 将新Bean定义放入beanDefinitionMap中,覆盖现有Bean定义
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (isAlias(beanName)) {
if (!isAllowBeanDefinitionOverriding()) {
String aliasedName = canonicalName(beanName);
if (containsBeanDefinition(aliasedName)) {
// 如果别名指向已存在的Bean定义
// alias for existing bean definition
throw new BeanDefinitionOverrideException(
beanName, beanDefinition, getBeanDefinition(aliasedName));
}
else {
// 如果别名指向不存在的Bean定义
// alias pointing to non-existing bean definition
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
   "Cannot register bean definition for bean '" + beanName +
   "' since there is already an alias for bean '" + aliasedName + "' bound.");
}
}
else {
// 移除别名
removeAlias(beanName);
}
}
if (hasBeanCreationStarted()) {
// 不能再修改启动时的集合元素(为了稳定的迭代)
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
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
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}

if (existingDefinition != null || containsSingleton(beanName)) {
// 重置Bean定义
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
// 清除按类型缓存
clearByTypeCache();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

向Spring的IOC容器中注册类的Bean定义信息,其实就是向beanDefinitionMap对象中添加元素,beanDefinitionMap对象本质上是一个ConcurrentHashMap对象。向beanDefinitionMap对象中添加的元素的Key为Bean的名称,Value为Bean的定义信息。

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
//##################省略其他代码###############
	this.beanDefinitionMap.put(beanName, beanDefinition);
//##################省略其他代码###############
}
1
2
3
4
5
6
7

beanDefinitionMap源码:

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
1

# 注册配置类流程源码解析

(1)AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class<?>... componentClasses)构造方法中调用了register()方法,传入componentClasses参数进行注册。

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
1
2
3
4
5

(2)解析AnnotationConfigApplicationContext类的register(Class<?>... componentClasses)方法

@Override
public void register(Class<?>... componentClasses) {
	//###########省略其他代码##############
this.reader.register(componentClasses);
//###########省略其他代码##############
}
1
2
3
4
5
6

(3)解析AnnotatedBeanDefinitionReader类的register(Class<?>... componentClasses)方法

public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}
1
2
3
4
5

(4)解析AnnotatedBeanDefinitionReader类的registerBean(Class<?> beanClass)方法

public void registerBean(Class<?> beanClass) {
doRegisterBean(beanClass, null, null, null, null);
}
1
2
3

(5)解析AnnotatedBeanDefinitionReader类的doRegisterBean(Class beanClass, String name, Class<? extends Annotation>[] qualifiers, Supplier supplier, BeanDefinitionCustomizer[] customizers)方法。

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {

AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
//###########################省略其他代码#############################
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//###########################省略其他代码#############################
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
1
2
3
4
5
6
7
8
9
10

(6)解析BeanDefinitionReaderUtils类的registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法

public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {

// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
//###########################省略其他代码#############################
}
1
2
3
4
5
6
7
8
9

在registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法中通过调用registry的registerBeanDefinition()方法来向IOC容器中注册Bean定义信息。

# 实例化流程源码解析

(1)AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class<?>... componentClasses)构造方法中会调用refresh()方法刷新IOC容器。

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
1
2
3
4
5

(2)解析AbstractApplicationContext类的refresh()方法

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
		//#############省略其他代码#####################
try {
//#############省略其他代码#####################
invokeBeanFactoryPostProcessors(beanFactory);
			//#############省略其他代码#####################
}
catch (BeansException ex) {
   //#############省略其他代码#####################
}
finally {
   //#############省略其他代码#####################
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在refresh()方法中调用了invokeBeanFactoryPostProcessors()方法。

(3)解析AbstractApplicationContext类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)方法

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
	//################省略其他代码####################
}
1
2
3
4

(4)解析PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors)方法

public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
	//#################省略其他代码##################
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
	invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
//#################省略其他代码##################
}
1
2
3
4
5
6
7

在invokeBeanFactoryPostProcessors()方法中会解析标注了@Configuration注解的类中标注了@Bean等注解的方法,生成相应的Bean定义信息注册到IOC容器中。这里主要关注的是标注了@Configuration注解的类的实例化过程

(5)解析PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory)方法

private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanFactory = beanFactory.getApplicationStartup().start("spring.context.bean-factory.post-process")
.tag("postProcessor", postProcessor::toString);
postProcessor.postProcessBeanFactory(beanFactory);
postProcessBeanFactory.end();
}
}
1
2
3
4
5
6
7
8

可以看到在invokeBeanFactoryPostProcessors()方法中,会循环遍历传递进来的所有postProcessors集合,每次循环时,都会使用一个postProcessor对象来接收postProcessors集合中的每一个元素,调用postProcessor对象的postProcessBeanFactory()方法,并传入beanFactory来实例化对象。

(6)解析ConfigurationClassPostProcessor类中的postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//##############省略其他代码###############
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
1
2
3
4
5
6

(7)解析ConfigurationClassPostProcessor类的enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory)方法

public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
//################省略其他代码########################
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
// If a @Configuration class gets proxied, always proxy the target class
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// Set enhanced subclass of the user-specified bean class
Class<?> configClass = beanDef.getBeanClass();
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
//################省略其他代码###################
beanDef.setBeanClass(enhancedClass);
}
}
enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet().size())).end();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory)方法主要是使用ConfigurationClassEnhancer对象的enhance()方法生成代理类,也就是使用CGLib生成代理类。

(8)解析ConfigurationClassEnhancer类的enhance(Class<?> configClass, ClassLoader classLoader)方法

public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
//###################省略其他代码###############
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
//###################省略其他代码###############
return enhancedClass;
}
1
2
3
4
5
6

enhance(Class<?> configClass, ClassLoader classLoader)方法中调用了createClass()方法创建代理类,在这之前先调用newEnhancer()方法实例化Enhancer对象。

(9)解析ConfigurationClassEnhancer类的newEnhancer(Class<?> configSuperClass, ClassLoader classLoader)方法

private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(configSuperClass);
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
enhancer.setUseFactory(false);
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setAttemptLoad(true);
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer;
}
1
2
3
4
5
6
7
8
9
10
11
12

newEnhancer()方法中主要是生成CGLib动态代理的Enhancer对象,后续会使用Enhancer对象生成代理类。

在newEnhancer()方法中为要生成的代理类设置了父类和接口,由于为要生成的代理类设置的接口为EnhancedConfiguration,同时,EnhancedConfiguration接口继承了BeanFactoryAware接口,所以,在后续生成的代理类中可以调用BeanFactoryAware接口的setBeanFactory(BeanFactory beanFactory)方法获取到beanFactory对象。

(10)解析ConfigurationClassEnhancer类的createClass(Enhancer enhancer)方法

private Class<?> createClass(Enhancer enhancer) {
Class<?> subclass = enhancer.createClass();
Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
return subclass;
}
1
2
3
4
5

在createClass(Enhancer enhancer)方法中主要调用了enhancer对象的createClass()方法来创建代理类,这里创建出来的代理类就是目标类的子类。。

(11)解析CALLBACKS

static final Callback[] CALLBACKS = new Callback[] {
new BeanMethodInterceptor(),
new BeanFactoryAwareMethodInterceptor(),
NoOp.INSTANCE
};
1
2
3
4
5

CALLBACKS是一个Callback类型的数组,数组中的每个元素都是一个Callback类型的对象。其中,BeanMethodInterceptor类和BeanFactoryAwareMethodInterceptor类也是拦截器类型。接下来,以BeanMethodInterceptor类为例进行介绍。

(12)解析BeanMethodInterceptor类

BeanMethodInterceptor实现了MethodInterceptor接口和ConditionalCallback接口,主要的作用就是对标注了@Bean的注解的方法进行拦截,执行intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs, MethodProxy cglibMethodProxy)方法,生成Bean的实例对象。

public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
					MethodProxy cglibMethodProxy) throws Throwable {
//如果已经创建了Bean的代理实例对象,则调用父类的方法。
if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
//#################省略其他代码###############
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
}
return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);   
}
1
2
3
4
5
6
7
8
9

上述代码能够保证在类上添加@Configuration注解后,只会为类生成一个代理对象。也就是上述代码的逻辑能够保证标注了@Configuration注解的类生成的代理类是单例模式的。

因为使用CGLib创建出来的代理类是目标类的子类,所以第一次执行上述代码片段时,会调用cglibMethodProxy的invokeSuper()方法执行父类的方法,也就是执行目标类的方法。第二次执行上述代码片段时,会调用resolveBeanReference()方法。

(13)解析BeanMethodInterceptor类的resolveBeanReference(Method beanMethod, Object[] beanMethodArgs, ConfigurableBeanFactory beanFactory, String beanName)方法

private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs, ConfigurableBeanFactory beanFactory, String beanName) {
//##############省略其他代码###############
boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
try {
//##############省略其他代码###############
Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
   beanFactory.getBean(beanName));
   //##############省略其他代码###############
return beanInstance;
}
finally {
   //##############省略其他代码###############
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

resolveBeanReference()方法中会通过beanFactory获取已经初始化好的Bean对象,并将这个已经初始化好的bean对象返回。并不会再进行第二次初始化的操作。所以在类上添加@Configuration注解后,Spring能够保证为类生成的代理类是单例的。

# 思考

# 1. Spring为何在创建IOC容器时先注册ConfigurationClassPostProcessor类后置处理器的Bean定义信息,随后才是注册标注了@Configuration注解的ConfigurationAnnotationConfig配置类的Bean定义信息?

Spring在创建IOC容器时首先注册ConfigurationClassPostProcessor类后置处理器的Bean定义信息,是因为ConfigurationClassPostProcessor是Spring框架用于处理带有@Configuration注解的类的核心组件。它负责扫描和处理这些配置类,进而解析其中的@Bean方法和其他相关注解。将其先注册为Bean定义,是为了在容器后续的启动和初始化过程中,能够尽早地获取到这个处理器,并利用它来解析和注册其他配置类中的Bean定义。

这种设计确保了Spring在正式解析和注册其他Bean之前,已经准备好了处理配置类的机制,从而能够有序、高效地处理整个配置过程,保证配置类中的元信息被正确处理。。

# 2. Spring为何先将类的Bean定义信息注册到IOC容器?为何不是直接注册实例化后的对象?

Spring先将类的Bean定义信息注册到IOC容器,而不是直接注册实例化后的对象,主要是因为这种方式提供了更高的灵活性和控制力。通过注册Bean定义(包括类的信息、构造方法、依赖关系等),Spring能够在需要的时候(通常是Bean被使用时)再创建Bean的实例。这种延迟初始化的策略有助于减少启动时的内存消耗和初始化时间,同时也可以通过配置来控制Bean的创建时机和生命周期。

此外,注册Bean定义还允许Spring在创建Bean实例时应用各种依赖注入(DI)和AOP(面向切面编程)特性,如自动装配、代理创建等,从而增强了Spring框架的功能。

# 3. Spring为何是在刷新IOC容器时,实例化标注了@Configuration注解的配置类的代理对象?为何不是在创建IOC容器时就进行实例化?

Spring在刷新IOC容器时实例化标注了@Configuration注解的配置类的代理对象,而不是在创建IOC容器时就进行实例化,主要是出于两个考虑:

  1. 延迟加载:通过延迟实例化配置类的代理对象,Spring可以在需要时再进行加载,这有助于减少应用启动时的初始化时间和内存消耗。
  2. 增强功能:配置类的代理对象在Spring中扮演着特殊角色,它们不仅包含了配置类的逻辑,还通过代理机制提供了额外的功能,如增强@Bean方法的调用(以确保每个@Bean方法只被调用一次并返回相同的实例)。Spring可以支持诸如@Bean方法的拦截,从而实现诸如条件判断、生命周期管理等功能。这种增强功能需要在容器启动和Bean创建过程中进行,因此延迟到容器刷新时再进行实例化是合理的。

# 1.2 @ComponentScans与@ComponentScan注解

@ComponentScans注解可以看作是@ComponentScan注解的一个数组,在@ComponentScans注解中可以多次标注@ComponentScan注解。@ComponentScan注解最核心的功能就是Spring IOC容器在刷新的时候会扫描对应包下标注了@Component注解、@Configuration注解、@Repository注解、@Service注解和@Controller等等注解的类,生成扫描到的类的Bean定义信息,整体流程与注册ConfigurationClassPostProcessor类的Bean定义信息的流程基本一致,最终都会将其保存到BeanFactory中的beanDefinitionMap中。

# 注解源码

@ComponentScans注解源码

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface ComponentScans {
	ComponentScan[] value();
}
1
2
3
4
5
6

@ComponentScan注解源码

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {

	@AliasFor("basePackages")
	String[] value() default {};

	@AliasFor("value")
	String[] basePackages() default {};

	Class<?>[] basePackageClasses() default {};

	Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

	Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

	ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

	String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;

	boolean useDefaultFilters() default true;

	Filter[] includeFilters() default {};

	Filter[] excludeFilters() default {};

	boolean lazyInit() default false;

	@Retention(RetentionPolicy.RUNTIME)
	@Target({})
	@interface Filter {

		FilterType type() default FilterType.ANNOTATION;

		@AliasFor("classes")
		Class<?>[] value() default {};

		@AliasFor("value")
		Class<?>[] classes() default {};

		String[] pattern() default {};

	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

@ComponentScan注解中的每个属性的含义如下所示。

  • value:作用同basePackages属性,String[]数组类型,指定要扫描的包名。如果指定了要扫描的包名,则Spring会扫描指定的包及其子包下的所有类。
  • basePackages:作用同value属性,String[]数组类型,指定要扫描的包名。如果指定了要扫描的包名,则Spring会扫描指定的包及其子包下的所有类。
  • basePackageClasses:Class<?>[]数组类型,指定要扫描的类的Class对象。
  • nameGenerator:Class<? extends BeanNameGenerator>类型,指定扫描类时,向IOC注入Bean对象时的命名规则。
  • scopeResolver:Class<? extends ScopeMetadataResolver>类型,扫描类时,用于处理并转换符合条件的Bean的作用范围。
  • scopedProxy:ScopedProxyMode类型,指定生成Bean对象时的代理方式,默认的代理方法是DEFAULT,也就是不使用代理。
  • resourcePattern:String类型,用于指定扫描的文件类型,默认是扫描指定包下的**/*.class。
  • useDefaultFilters:boolean类型,是否自动检测@Component @Repository @Service @Controller注解,默认是true。
  • includeFilters:Filter[]数组类型,自定义组件扫描过滤规则,符合过滤规则的类的Bean定义信息会被注册到IOC容器中。includeFilters表示只包含对应的规则,当使用includeFilters()来指定只包含哪些注解标注的类时,需要禁用默认的过滤规则,也就是需要将useDefaultFilters属性设置为false。并且,除了符合过滤规则的类外,Spring内置的如下名称的类的Bean定义信息注册到IOC容器时不受过滤规则限制,如下所示。
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
1
2
3
4
  • excludeFilters:Filter[]数组类型,自定义组件扫描过滤规则,excludeFilters表示排除使用对应的规则,符合过滤规则的类的Bean定义信息不会被注册到IScopedProxyMode枚举类表示Spring指定生成Bean对象时的代理方式OC容器中。
  • lazyInit:boolean类型,表示Spring扫描组件时是否采用懒加载 ,默认false,表示不开启懒加载。

@Filter注解中的每个属性的含义如下所示。

  • type:FilterType类型,表示过滤规则的类型。
  • value:Class<?>[]数组类型,过滤符合规则的类,作用同classes属性。
  • classes:Class<?>[]数组类型,过滤符合规则的类,作用同value属性。
  • pattern:如果FilterType取值为ASPECTJ,则此属性表示ASPECTJ表达式。

ScopedProxyMode枚举类表示Spring指定生成Bean对象时的代理方式:

public enum ScopedProxyMode {
	DEFAULT,
	NO,
	INTERFACES,
	TARGET_CLASS
}
1
2
3
4
5
6

ScopedProxyMode类每个属性的含义:

  • DEFAULT:默认的代理方式,也就是不使用代理,除非在component-scan级别使用了不同的配置。
  • NO:不使用代理。
  • INTERFACES:基于JDK动态代理实现接口代理对象。
  • TARGET_CLASS:基于CGLib动态代理创建类代理对象。

FilterType枚举类表示Spring扫描类时的过滤类型:

public enum FilterType {
	ANNOTATION,
	ASSIGNABLE_TYPE,
	ASPECTJ,
	REGEX,
	CUSTOM
}
1
2
3
4
5
6
7

FilterType类每个属性的含义:

  • ANNOTATION:按照注解进行过滤。
  • ASSIGNABLE_TYPE:按照给定的类型进行过滤。
  • ASPECTJ:按照ASPECTJ表达式进行过滤。
  • REGEX:按照正则表达式进行过滤。
  • CUSTOM:按照自定义规则进行过滤,使用自定义过滤规则时,自定义的过滤器需要实现org.springframework.core.type.filter.TypeFilter接口。

# 源码时序图

图2-1

图2-2

图2-3

# 源码解析

(1)运行ComponentScanTest类的main()方法。

public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ComponentScanConfig.class);
String[] names = context.getBeanDefinitionNames();
Arrays.stream(names).forEach(System.out::println);
}
1
2
3
4
5

(2)解析AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class<?>... componentClasses)构造方法

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
1
2
3
4
5

(3)解析AbstractApplicationContext类的refresh()方法

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//############省略其他代码##############
try {
//############省略其他代码##############
invokeBeanFactoryPostProcessors(beanFactory);
   //############省略其他代码##############
}catch (BeansException ex) {
//############省略其他代码##############
}finally {
//############省略其他代码##############
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

(4)解析AbstractApplicationContext类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)方法

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
1
2
3
4
5
6
7

(5)解析PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors)方法

public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

//############省略其他代码##############
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

// 首先,调用实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();

// 接着,调用实现Ordered接口的BeanDefinitionRegistryPostProcessor
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();

// 最后,循环调用其他BeanDefinitionRegistryPostProcessor,直到没有新的出现
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
}
//############省略其他代码##############
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

BeanDefinitionRegistryPostProcessor的实现类在执行逻辑上会有先后顺序,并且最终都会调用invokeBeanDefinitionRegistryPostProcessors()方法。

(6)解析PostProcessorRegistrationDelegate类的invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup)方法

private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {

for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
// 启动一个名为 "spring.context.beandef-registry.post-process" 的启动步骤,并为其添加一个标签 "postProcessor",标签的值为 postProcessor 的字符串表示形式
StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
.tag("postProcessor", postProcessor::toString);
// 调用 postProcessor 的 postProcessBeanDefinitionRegistry 方法,对 BeanDefinitionRegistry 注册Bean的定义信息
postProcessor.postProcessBeanDefinitionRegistry(registry);
// 结束启动步骤
postProcessBeanDefRegistry.end();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13

在invokeBeanDefinitionRegistryPostProcessors()方法中,会循环遍历postProcessors集合中的每个元素,调用postProcessBeanDefinitionRegistry()方法注册Bean的定义信息。

(7)解析ConfigurationClassPostProcessor类的postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
	//##########省略其他代码###################
processConfigBeanDefinitions(registry);
}
1
2
3
4
5

(8)解析ConfigurationClassPostProcessor类的processConfigBeanDefinitions(BeanDefinitionRegistry registry)方法

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
//############省略其他代码#################
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);

// 存储待解析的 Bean 定义持有者
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
// 存储已经解析过的配置类
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
// 启动一个名为 "spring.context.config-classes.parse" 的启动步骤
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
// 解析配置类
parser.parse(candidates);
// 验证配置类
parser.validate();
// 获取解析后的配置类集合
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
// 移除已经解析过的配置类
configClasses.removeAll(alreadyParsed);

// 根据模型内容读取并创建 Bean 定义
// Read the model and create bean definitions based on its content
if (this.reader == null) {
// 初始化 Bean 定义读取器
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// 加载 Bean 定义
this.reader.loadBeanDefinitions(configClasses);
// 将已解析的配置类添加到已解析集合中
alreadyParsed.addAll(configClasses);
// 结束启动步骤,并标记解析的配置类数量
processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

// 清空待解析的 Bean 定义持有者集合
candidates.clear();
// 如果当前注册的 Bean 定义数量大于候选名称的数量
if (registry.getBeanDefinitionCount() > candidateNames.length) {
// 获取当前所有注册的 Bean 名称
String[] newCandidateNames = registry.getBeanDefinitionNames();
// 将候选名称转换为集合
Set<String> oldCandidateNames = Set.of(candidateNames);
// 存储已经解析过的配置类名称
Set<String> alreadyParsedClasses = new HashSet<>();
// 遍历已解析的配置类
for (ConfigurationClass configurationClass : alreadyParsed) {
// 添加配置类名称到已解析集合中
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
// 遍历新的候选名称
for (String candidateName : newCandidateNames) {
// 如果旧的候选名称集合中不包含当前候选名称
if (!oldCandidateNames.contains(candidateName)) {
// 获取 Bean 定义
BeanDefinition bd = registry.getBeanDefinition(candidateName);
// 判断 Bean 定义是否是配置类候选
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
// 并且配置类名称不在已解析集合中
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
// 将新的 Bean 定义持有者添加到待解析集合中
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
// 更新候选名称数组
candidateNames = newCandidateNames;
}
}
// 循环直到待解析集合为空
while (!candidates.isEmpty());
//############省略其他代码#################
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

在processConfigBeanDefinitions()方法中,创建了一个ConfigurationClassParser类型的对象parser,并且调用了parser的parse()方法来解析类的配置信息。

(9)解析ConfigurationClassParser类的parse(Set configCandidates)方法

public void parse(Set<BeanDefinitionHolder> configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
// 如果 BeanDefinition 是 AnnotatedBeanDefinition 类型
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
// 如果 BeanDefinition 是 AbstractBeanDefinition 类型,并且存在 BeanClass
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
// 其他情况
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
// 如果发生 BeanDefinitionStoreException 异常,则直接抛出
throw ex;
}
catch (Throwable ex) {
// 如果发生其他异常,则包装为 BeanDefinitionStoreException 异常并抛出
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
this.deferredImportSelectorHandler.process();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

(10)解析ConfigurationClassParser类的parse(AnnotationMetadata metadata, String beanName)方法

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}
1
2
3

(11)解析ConfigurationClassParser类的processConfigurationClass(ConfigurationClass configClass, Predicate filter)方法

protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
//###############省略其他代码####################
// 递归处理配置类及其超类层次结构
SourceClass sourceClass = asSourceClass(configClass, filter);
do {
// 处理配置类
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
while (sourceClass != null);
// 将配置类放入配置类集合中
this.configurationClasses.put(configClass, configClass);
}
1
2
3
4
5
6
7
8
9
10
11
12

在processConfigurationClass()方法中,会通过do-while()循环获取配置类和其父类的注解信息,SourceClass类中会封装配置类上注解的详细信息。

(12)解析ConfigurationClassParser类的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)方法

protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
//##############省略其他代码################
// 处理任何@ComponentScan注解
// Process any @ComponentScan annotations
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// 如果配置类被注解为@ComponentScan -> 立即执行扫描
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// 检查扫描到的定义集合中是否有其他配置类,如果需要则递归解析
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
// 解析配置类
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
  	//##############省略其他代码################
// No superclass -> processing is complete
return null;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

在上述处理@ComponentScan注解的逻辑中,通过componentScanParser的parse()方法对@ComponentScan注解进行解析。

(13)解析ComponentScanAnnotationParser类的parse(AnnotationAttributes componentScan, String declaringClass)方法

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, String declaringClass) {
// 创建ClassPathBeanDefinitionScanner实例
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
// 获取BeanNameGenerator类的Class对象
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
// 判断是否使用继承的BeanNameGenerator
boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
// 设置BeanNameGenerator
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
 BeanUtils.instantiateClass(generatorClass));
// 获取ScopedProxyMode枚举值
ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
// 设置ScopedProxyMode
scanner.setScopedProxyMode(scopedProxyMode);
}
else {
// 获取ScopeMetadataResolver类的Class对象
Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
// 设置ScopeMetadataResolver
scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
}
// 设置资源匹配模式
scanner.setResourcePattern(componentScan.getString("resourcePattern"));
// 遍历includeFilters
for (AnnotationAttributes includeFilterAttributes : componentScan.getAnnotationArray("includeFilters")) 	{
// 创建TypeFilter列表
List<TypeFilter> typeFilters = TypeFilterUtils.createTypeFiltersFor(includeFilterAttributes, this.environment,
this.resourceLoader, this.registry);
// 遍历TypeFilter列表,并添加到scanner中
for (TypeFilter typeFilter : typeFilters) {
scanner.addIncludeFilter(typeFilter);
}
}
// 遍历excludeFilters
for (AnnotationAttributes excludeFilterAttributes : componentScan.getAnnotationArray("excludeFilters")) 	{
// 创建TypeFilter列表
List<TypeFilter> typeFilters = TypeFilterUtils.createTypeFiltersFor(excludeFilterAttributes, this.environment,
this.resourceLoader, this.registry);
// 遍历TypeFilter列表,并添加到scanner中
for (TypeFilter typeFilter : typeFilters) {
scanner.addExcludeFilter(typeFilter);
}
}

// 获取lazyInit的值
boolean lazyInit = componentScan.getBoolean("lazyInit");
if (lazyInit) {
// 设置Bean定义默认的懒加载属性
scanner.getBeanDefinitionDefaults().setLazyInit(true);
}

// 创建basePackages集合
Set<String> basePackages = new LinkedHashSet<>();
// 获取basePackages数组
String[] basePackagesArray = componentScan.getStringArray("basePackages");
// 遍历basePackages数组
for (String pkg : basePackagesArray) {
// 解析并添加包名到basePackages集合中
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
   ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
Collections.addAll(basePackages, tokenized);
}
// 遍历basePackageClasses数组
for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
// 获取包名并添加到basePackages集合中
basePackages.add(ClassUtils.getPackageName(clazz));
}
// 如果basePackages集合为空,则添加声明类的包名到集合中
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
}

// 添加自定义的excludeFilter
scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
@Override
protected boolean matchClassName(String className) {
// 判断是否为声明类的类名
return declaringClass.equals(className);
}
});
		// 执行扫描并返回结果
return scanner.doScan(StringUtils.toStringArray(basePackages));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

在parse()方法中,会创建一个ClassPathBeanDefinitionScanner类型的扫描器scanner,将@ComponentScan注解上配置的信息都设置到扫描器scanner中,最后调用扫描器scanner的doScan()方法进行扫描。

(14)解析ClassPathBeanDefinitionScanner类的doScan(String... basePackages)方法

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
// 断言basePackages不为空,至少指定一个基础包
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
// 在基础包中查找候选组件
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
// 解析候选组件的作用域元数据
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
// 设置候选组件的作用域
candidate.setScope(scopeMetadata.getScopeName());
// 生成候选组件的Bean名称
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
// 如果候选组件是AbstractBeanDefinition类型
if (candidate instanceof AbstractBeanDefinition) {
// 对候选组件进行后处理
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
// 如果候选组件是AnnotatedBeanDefinition类型
if (candidate instanceof AnnotatedBeanDefinition) {
// 处理候选组件的通用定义注解
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
// 检查候选组件是否满足条件
if (checkCandidate(beanName, candidate)) {
// 创建BeanDefinitionHolder对象
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
// 应用作用域代理模式
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 将BeanDefinitionHolder添加到beanDefinitions集合中
beanDefinitions.add(definitionHolder);
// 注册BeanDefinitionHolder到注册中心
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
// 返回beanDefinitions集合
return beanDefinitions;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

在doScan()方法中,会遍历传入的每个包路径,调用findCandidateComponents()方法来扫描带有注解(例如@Component注解)的类。

(15)解析ClassPathScanningCandidateComponentProvider类的findCandidateComponents(String basePackage)方法

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
// 如果组件索引不为空,并且索引支持包含过滤器
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
// 从索引中添加候选组件
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
// 扫描候选组件
return scanCandidateComponents(basePackage);
}
}
1
2
3
4
5
6
7
8
9
10
11

(16)解析ClassPathScanningCandidateComponentProvider类的scanCandidateComponents(String basePackage)方法

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
for (Resource resource : resources) {
String filename = resource.getFilename();
if (filename != null && filename.contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
// 忽略classpath中CGLIB生成的类
// Ignore CGLIB-generated classes in the classpath
continue;
}
if (traceEnabled) {
// 跟踪日志,扫描资源
logger.trace("Scanning " + resource);
}
try {
// 获取资源的元数据读取器
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
// 判断是否为候选组件
if (isCandidateComponent(metadataReader)) {
// 创建扫描到的泛型Bean定义
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
// 设置资源来源
sbd.setSource(resource);
// 再次判断是否为候选组件
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 (FileNotFoundException ex) {
if (traceEnabled) {
// 跟踪日志,忽略不可读资源
logger.trace("Ignored non-readable " + resource + ": " + ex.getMessage());
}
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
// 抛出Bean定义存储异常,读取候选组件类失败
"Failed to read candidate component class: " + resource, ex);
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
return candidates;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

在scanCandidateComponents()方法中,会调用isCandidateComponent()方法来判断当前注解是不是要扫描的注解。

(17)解析ClassPathScanningCandidateComponentProvider类的isCandidateComponent(MetadataReader metadataReader)方法

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
// 遍历排除过滤器列表
for (TypeFilter tf : this.excludeFilters) {
// 如果当前过滤器匹配给定的元数据读取器
if (tf.match(metadataReader, getMetadataReaderFactory())) {
// 返回false,表示不是候选组件
return false;
}
}
// 遍历包含过滤器列表
for (TypeFilter tf : this.includeFilters) {
// 如果当前过滤器匹配给定的元数据读取器
if (tf.match(metadataReader, getMetadataReaderFactory())) {
// 调用isConditionMatch方法判断条件是否匹配
return isConditionMatch(metadataReader);
}
}
// 如果都不匹配,则返回false,表示不是候选组件
return false;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

isCandidateComponent()方法的逻辑还是比较简单的,就是遍历匹配excludeFilters和includeFilters指定的规则。

优先匹配excludeFilters指定的规则,如果匹配excludeFilters指定的规则,直接返回false。接下来,匹配includeFilters指定的规则,匹配成功,则调用isConditionMatch()方法进行条件匹配。

其中,对于includeFilters而言,默认的过滤规则如下所示。

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("jakarta.annotation.ManagedBean", cl)), false));
logger.trace("JSR-250 'jakarta.annotation.ManagedBean' found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-250 1.1 API (as included in Jakarta EE) not available - simply skip.
}
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("jakarta.inject.Named", cl)), false));
logger.trace("JSR-330 'jakarta.inject.Named' annotation found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

对于includeFilters而言,默认的过滤规则会匹配@Component注解,JSR-250中的注解和JSR-330中的注解。

(18)回到ClassPathScanningCandidateComponentProvider类的scanCandidateComponents(String basePackage)方法

在ClassPathScanningCandidateComponentProvider类的scanCandidateComponents(String basePackage)方法中,会将标注了@Component注解,JSR-250中的注解和JSR-330中的注解的类信息封装成ScannedGenericBeanDefinition类对象,也就是类的Bean定义信息。

ScannedGenericBeanDefinition类的构造方法如下所示。

public ScannedGenericBeanDefinition(MetadataReader metadataReader) {
Assert.notNull(metadataReader, "MetadataReader must not be null");
this.metadata = metadataReader.getAnnotationMetadata();
setBeanClassName(this.metadata.getClassName());
setResource(metadataReader.getResource());
}
1
2
3
4
5
6

(19)回到ClassPathBeanDefinitionScanner类的doScan(String... basePackages)方法

在ClassPathBeanDefinitionScanner类的doScan(String... basePackages)方法中,会将扫描到的类的Bean定义信息注册到IOC容器中,如下代码片段所示。

if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
1
2
3
4
5
6
7

在doScan()方法中,会调用registerBeanDefinition()注册Bean定义信息。

(20)解析ClassPathBeanDefinitionScanner类的registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法

protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
1
2
3

在方法中直接调用了BeanDefinitionReaderUtils类的registerBeanDefinition()方法。

(21)解析BeanDefinitionReaderUtils类的registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法。

public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {

// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
	//###########省略其他代码###################
}
1
2
3
4
5
6
7
8
9

在上述代码中,会继续调用BeanDefinitionRegistry类型的对象registry的registerBeanDefinition()方法,将类的Bean定义信息注册到IOC容器。

(22)解析DefaultListableBeanFactory类的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
	//##############省略其他代码#################
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
//##############省略其他代码#################
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
//##############省略其他代码#################
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
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
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

Spring会将扫描到的标注了符合过滤规则的注解的类封装成对应的Bean定义信息,最终会将这些Bean定义信息注册到beanDefinitionMap中。

# 思考

# 1.Spring扫描指定包的逻辑为何复杂?

Spring扫描指定包的逻辑之所以看起来复杂,主要是因为其设计需要兼顾灵活性、可扩展性和性能。Spring的组件扫描(Component Scanning)机制允许开发者通过注解(如@Component、@Service、@Repository等)自动注册bean到Spring的IoC容器中,而无需显式地在XML配置文件中声明每一个bean。为了实现这一功能,Spring需要:

  1. 灵活性:允许开发者自定义扫描的包路径、过滤规则等,以适应不同的项目结构和需求。
  2. 可扩展性:通过提供TypeFilter接口等机制,允许开发者自定义过滤逻辑,以排除或包含特定的类。
  3. 性能:在大型项目中,可能需要扫描成百上千个类,Spring的扫描机制需要优化以减少扫描时间和内存消耗。

为了实现这些目标,Spring的组件扫描逻辑需要处理多种情况,包括但不限于:处理类路径资源、解析注解、应用过滤规则、注册bean定义等。

# 2.配置类上不标注@ComponentScans或@ComponentScan能扫描到哪些包下的类?

如果在Spring Boot的配置类(通常是带有@Configuration注解的类)上不标注@ComponentScans或@ComponentScan注解,Spring Boot会采用默认行为。具体来说,Spring Boot会从主应用类(带有@SpringBootApplication注解的类)所在的包开始,扫描这个包及其子包下的所有类。这意味着,只要你的@Component注解的类位于主应用类所在的包或其子包下,它们就会被自动扫描并注册到IoC容器中。

# 3.@ComponentScan注解中的basePackages或value属性可以设置任意包名吗?

是的,@ComponentScan注解中的basePackages或value属性可以设置任意包名(前提是这些包在类路径上确实存在)。这些属性用于指定Spring应该扫描哪些包以查找带有@Component、@Service、@Repository等注解的类。如果指定的包不存在于应用的类路径中,Spring在启动时会抛出异常,提示找不到指定的包。

因此,当使用@ComponentScan注解时,务必确保指定的包是真实存在的,并且包含了你想要自动注册为Spring bean的类。如果希望从多个不同的包中扫描组件,可以使用@ComponentScans注解,并在其中指定多个@ComponentScan。

# 1.3 @Bean注解

@Bean注解可以标注到方法上,将当前方法的返回值注入到IOC容器中。@Bean注解也可以标注到注解上,作为元注解使用。

# 注解源码

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
	//Since: 4.3.3
	@AliasFor("name")
	String[] value() default {};

	@AliasFor("value")
	String[] name() default {};
	
//Since: 5.1
	boolean autowireCandidate() default true;

	String initMethod() default "";

	String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

注解中各个属性的含义如下所示。

  • name:String[]数组类型,指定注入到IOC容器中的Bean的名称,可以指定多个名称。如果不指定name属性和value属性的值,则注入到IOC容器中的Bean的名称默认是方法的名称。
  • value:String[]数组类型,作用与name属性相同。
  • autowireCandidate:boolean类型,表示是否支持自动按照类型注入到其他的Bean中。此属性会影响@Autowired注解,不会响应@Resource注解,默认为true,表示支持自动按照类型注入到其他的Bean中。
  • initMethod:指定初始化的方法。
  • destroyMethod:指定销毁的方法。

# 源码时序图

# 注册Bean的流程

图3-1

图3-2

# 调用初始化方法

图3-3

图3-4

# 调用销毁方法

图3-5

# 源码解析

# 注册bean的流程

(1)运行BeanTest类的main()方法。

在BeanTest类的main()方法中调用了AnnotationConfigApplicationContext类的构造方法,并传入了ComponentScanConfig类的Class对象来创建IOC容器。接下来,会进入AnnotationConfigApplicationContext类的构造方法。

(2)解析AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class<?>... componentClasses)构造方法

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
1
2
3
4
5

(3)解析AbstractApplicationContext类的refresh()方法

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//############省略其他代码##############
try {
//############省略其他代码##############
invokeBeanFactoryPostProcessors(beanFactory);
   //############省略其他代码##############
}catch (BeansException ex) {
//############省略其他代码##############
}finally {
//############省略其他代码##############
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

(4)解析AbstractApplicationContext类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)方法

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
1
2
3
4
5
6
7

(5)解析PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors)方法

public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

//############省略其他代码##############
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();

// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();

// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
}
//############省略其他代码##############
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

在PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors)方法中,BeanDefinitionRegistryPostProcessor的实现类在执行逻辑上会有先后顺序,并且最终都会调用invokeBeanDefinitionRegistryPostProcessors()方法。

(6)解析PostProcessorRegistrationDelegate类的invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup)方法

private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {

for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
.tag("postProcessor", postProcessor::toString);
postProcessor.postProcessBeanDefinitionRegistry(registry);
postProcessBeanDefRegistry.end();
}
}
1
2
3
4
5
6
7
8
9
10

在invokeBeanDefinitionRegistryPostProcessors()方法中,会循环遍历postProcessors集合中的每个元素,调用postProcessBeanDefinitionRegistry()方法注册Bean的定义信息。

(7)解析ConfigurationClassPostProcessor类的postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
	//##########省略其他代码###################
processConfigBeanDefinitions(registry);
}
1
2
3
4
5

在postProcessBeanDefinitionRegistry()方法中,会调用processConfigBeanDefinitions()方法。

(8)解析ConfigurationClassPostProcessor类的processConfigBeanDefinitions(BeanDefinitionRegistry registry)方法

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
//############省略其他代码#################
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);

Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
parser.parse(candidates);
parser.validate();
//############省略其他代码#################
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
//############省略其他代码#################
}
while (!candidates.isEmpty());
//############省略其他代码#################
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

在processConfigBeanDefinitions()方法中,创建了一个ConfigurationClassParser类型的对象parser,并且调用了parser的parse()方法来解析类的配置信息。

(9)解析ConfigurationClassParser类的parse(Set configCandidates)方法

public void parse(Set<BeanDefinitionHolder> configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
this.deferredImportSelectorHandler.process();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

(10)解析ConfigurationClassParser类的parse(AnnotationMetadata metadata, String beanName)方法

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}
1
2
3

(11)解析ConfigurationClassParser类的processConfigurationClass(ConfigurationClass configClass, Predicate filter)方法

protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
//###############省略其他代码####################
SourceClass sourceClass = asSourceClass(configClass, filter);
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
while (sourceClass != null);
this.configurationClasses.put(configClass, configClass);
}
1
2
3
4
5
6
7
8
9

在processConfigurationClass()方法中,会通过do-while()循环获取配置类和其父类的注解信息,SourceClass类中会封装配置类上注解的详细信息。在在processConfigurationClass()方法中,调用了doProcessConfigurationClass()方法。

(12)解析ConfigurationClassParser类的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)方法

protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
//##################省略其他代码##################
// Process individual @Bean methods
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
//##################省略其他代码##################
// No superclass -> processing is complete
return null;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

(13)解析ConfigurationClassParser类的retrieveBeanMethodMetadata(SourceClass sourceClass)方法

private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
AnnotationMetadata original = sourceClass.getMetadata();
Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());
if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {
try {
AnnotationMetadata asm = this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();
Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());
if (asmMethods.size() >= beanMethods.size()) {
Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size());
for (MethodMetadata asmMethod : asmMethods) {
for (MethodMetadata beanMethod : beanMethods) {
if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) {
selectedMethods.add(beanMethod);
break;
}
}
}
if (selectedMethods.size() == beanMethods.size()) {
beanMethods = selectedMethods;
}
}
}
catch (IOException ex) {
logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);
}
}
return beanMethods;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

在retrieveBeanMethodMetadata()方法中主要是解析@Bean注解,并且将解析到的方法元数据存入 Set集合中并返回。

(14)回到ConfigurationClassParser类的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)方法。

Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
1
2
3
4

调用retrieveBeanMethodMetadata()方法获取到标注了@Bean注解的方法的元数据集合后,遍历方法的元数据集合,将方法的元数据methodMetadata和配置类configClass传入BeanMethod类的构造方法,创建BeanMethod对象,并调用configClass的addBeanMethod()方法传入创建的BeanMethod对象。

configClass的addBeanMethod()方法的源码

void addBeanMethod(BeanMethod method) {
this.beanMethods.add(method);
}
1
2
3

在addBeanMethod()方法中,调用了beanMethods的add()方法添加BeanMethod对象。

beanMethods的源码详见:org.springframework.context.annotation.ConfigurationClass#beanMethods,如下所示。

private final Set<BeanMethod> beanMethods = new LinkedHashSet<>();
1

beanMethods是一个LinkedHashSet类型的集合。也就是说,在ConfigurationClassParser类的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)方法中,会将解析出的标注了@Bean注解的元数据封装成BeanMethod对象,添加到一个LinkedHashSet类型的beanMethods集合中。

(15)回到ConfigurationClassPostProcessor类的processConfigBeanDefinitions(BeanDefinitionRegistry registry)方法

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
//############省略其他代码#################
do {
//############省略其他代码#################
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
//############省略其他代码#################
}
while (!candidates.isEmpty());
//############省略其他代码#################
}
1
2
3
4
5
6
7
8
9
10
11
12

在processConfigBeanDefinitions()方法的do-while()循环中,调用了reader的loadBeanDefinitions()方法来加载Bean的定义信息。

(16)解析ConfigurationClassBeanDefinitionReader类的loadBeanDefinitions(Set configurationModel)方法

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
1
2
3
4
5
6

在loadBeanDefinitions()方法中,会循环遍历传入的configurationModel集合,并调用loadBeanDefinitionsForConfigurationClass()方法处理遍历的每个元素。

(17)解析ConfigurationClassBeanDefinitionReader类的loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator)方法

private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
//###############省略其他代码################
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
	//###############省略其他代码################
}
1
2
3
4
5
6
7
8

在loadBeanDefinitionsForConfigurationClass()方法中,会循环遍历通过configClass获取到的BeanMethod集合,并调用loadBeanDefinitionsForBeanMethod()方法处理遍历的每个BeanMethod对象。

(18)解析ConfigurationClassBeanDefinitionReader类的loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod)方法

private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
ConfigurationClass configClass = beanMethod.getConfigurationClass();
MethodMetadata metadata = beanMethod.getMetadata();
String methodName = metadata.getMethodName();
if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
configClass.skippedBeanMethods.add(methodName);
return;
}
if (configClass.skippedBeanMethods.contains(methodName)) {
return;
}
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
Assert.state(bean != null, "No @Bean annotation attributes");
List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
for (String alias : names) {
this.registry.registerAlias(beanName, alias);
}
if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
   beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
   "' clashes with bean name for containing configuration class; please make those names unique!");
}
return;
}

ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata, beanName);
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));

if (metadata.isStatic()) {
// static @Bean method
if (configClass.getMetadata() instanceof StandardAnnotationMetadata sam) {
beanDef.setBeanClass(sam.getIntrospectedClass());
}
else {
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
}
beanDef.setUniqueFactoryMethodName(methodName);
}
else {
// instance @Bean method
beanDef.setFactoryBeanName(configClass.getBeanName());
beanDef.setUniqueFactoryMethodName(methodName);
}

if (metadata instanceof StandardMethodMetadata sam) {
beanDef.setResolvedFactoryMethod(sam.getIntrospectedMethod());
}

beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);

boolean autowireCandidate = bean.getBoolean("autowireCandidate");
if (!autowireCandidate) {
beanDef.setAutowireCandidate(false);
}

String initMethodName = bean.getString("initMethod");
if (StringUtils.hasText(initMethodName)) {
beanDef.setInitMethodName(initMethodName);
}

String destroyMethodName = bean.getString("destroyMethod");
beanDef.setDestroyMethodName(destroyMethodName);
ScopedProxyMode proxyMode = ScopedProxyMode.NO;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
if (attributes != null) {
beanDef.setScope(attributes.getString("value"));
proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = ScopedProxyMode.NO;
}
}
BeanDefinition beanDefToRegister = beanDef;
if (proxyMode != ScopedProxyMode.NO) {
BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
new BeanDefinitionHolder(beanDef, beanName), this.registry,
proxyMode == ScopedProxyMode.TARGET_CLASS);
beanDefToRegister = new ConfigurationClassBeanDefinition(
(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata, beanName);
}

if (logger.isTraceEnabled()) {
logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",
   configClass.getMetadata().getClassName(), beanName));
}
this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

在loadBeanDefinitionsForBeanMethod()方法中解析了@Bean注解中的属性信息,并将解析出的信息封装到一个BeanDefinition对象中,最终会调用registry对象的registerBeanDefinition()方法将封装的BeanDefinition对象注册到IOC容器中。

(19)解析DefaultListableBeanFactory类的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
	//##############省略其他代码#################
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
//##############省略其他代码#################
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
//##############省略其他代码#################
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
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
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

Spring会解析这些标注了@Bean注解的方法,将解析出的信息封装成BeanDefinition对象注册到beanDefinitionMap中。

# 调用初始化方法

(1)在BeanTest类的main()方法中,会调用AnnotationConfigApplicationContext类的构造方法创建IOC容器。

(2)解析AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class<?>... componentClasses)方法

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
1
2
3
4
5

(3)解析AbstractApplicationContext类的refresh()方法

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
 /*************省略其他代码**************/
try {
/*************省略其他代码**************/
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
 			/*************省略其他代码**************/
}
catch (BeansException ex) {
/*************省略其他代码**************/
}
finally {
/*************省略其他代码**************/
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

在AbstractApplicationContext类的refresh()方法中,会调用finishBeanFactoryInitialization()方法实例化未延迟创建的单例Bean。

(4)解析AbstractApplicationContext类的finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory)方法

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
/*************省略其他代码**************/
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
1
2
3
4
5

在AbstractApplicationContext类的finishBeanFactoryInitialization()方法中,会调用beanFactory的preInstantiateSingletons()方法来创建非懒加载的Bean。

(5)解析DefaultListableBeanFactory类的preInstantiateSingletons()方法

@Override
public void preInstantiateSingletons() throws BeansException {
   /*************省略其他代码**************/
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
/*************省略其他代码**************/
}
else {
getBean(beanName);
}
}
}
	/*************省略其他代码**************/
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在DefaultListableBeanFactory类的preInstantiateSingletons()方法中,会循环遍历所有非懒加载的单例Bean的名称,调用getBean()方法创建单例Bean对象。

(6)解析AbstractBeanFactory类的getBean(String name)方法

@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
1
2
3
4

在AbstractBeanFactory类的getBean()方法中,会调用doGetBean()方法创建Bean对象。

(7)解析AbstractBeanFactory类的doGetBean(String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly)方法

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
String beanName = transformedBeanName(name);
Object beanInstance;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
/***********省略其他代码*************/
}
else {
/***********省略其他代码*************/
try {
/***********省略其他代码*************/
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
/***********省略其他代码*************/
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
			/***********省略其他代码*************/
}
catch (BeansException ex) {
   /***********省略其他代码*************/
}
finally {
   /***********省略其他代码*************/
}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

在AbstractBeanFactory类的doGetBean()方法中,会调用createBean()方法创建Bean对象。

(8)解析AbstractAutowireCapableBeanFactory类的createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)方法

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
	/***********省略其他代码*************/
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
/***********省略其他代码*************/
}
catch (Throwable ex) {
/***********省略其他代码*************/
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在AbstractAutowireCapableBeanFactory类的createBean()方法中,会调用doCreateBean()方法创建Bean对象。

(9)解析AbstractAutowireCapableBeanFactory类的doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)方法

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
	/***********省略其他代码*************/
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
   /***********省略其他代码*************/
}
	/***********省略其他代码*************/
return exposedObject;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

在AbstractAutowireCapableBeanFactory类的doCreateBean()方法中,会调用initializeBean()方法初始化Bean对象。

(10)解析AbstractAutowireCapableBeanFactory类的initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd)方法

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
/***********省略其他代码*************/
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
   /***********省略其他代码*************/
}
/***********省略其他代码*************/
return wrappedBean;
}
1
2
3
4
5
6
7
8
9
10
11

在AbstractAutowireCapableBeanFactory类的initializeBean()方法中,会调用invokeInitMethods()方法来调用初始化方法。

(11)解析AbstractAutowireCapableBeanFactory类的invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)方法

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
	/***********省略其他代码*************/
if (mbd != null && bean.getClass() != NullBean.class) {
String[] initMethodNames = mbd.getInitMethodNames();
if (initMethodNames != null) {
for (String initMethodName : initMethodNames) {
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd, initMethodName);
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在AbstractAutowireCapableBeanFactory类的invokeInitMethods()方法中,会调用invokeCustomInitMethod()方法来执行自定义的初始化方法。

(12)解析AbstractAutowireCapableBeanFactory类的invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd, String initMethodName)方法

protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd, String initMethodName)  throws Throwable {
Method initMethod = (mbd.isNonPublicAccessAllowed() ? BeanUtils.findMethod(bean.getClass(), initMethodName) : ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
	/***********省略其他代码*************/
Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod, bean.getClass());
try {
ReflectionUtils.makeAccessible(methodToInvoke);
methodToInvoke.invoke(bean);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
1
2
3
4
5
6
7
8
9
10
11
12

在AbstractAutowireCapableBeanFactory类的invokeCustomInitMethod()方法中,会通过Java的反射机制调用自定义的初始化方法。

# 调用销毁方法

(1)在BeanTest类的main()方法中,会调用context对象的close()方法来关闭IOC容器

public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
/*********省略其他代码***********/
context.close();
}
1
2
3
4
5

(2)解析AbstractApplicationContext类的close()方法

@Override
public void close() {
synchronized (this.startupShutdownMonitor) {
doClose();
/*********省略其他代码***********/
}
}
1
2
3
4
5
6
7

在AbstractApplicationContext类的close()方法中,调用了doClose()方法来关闭IOC容器。

(3)解析AbstractApplicationContext类的doClose()方法

protected void doClose() {
// Check whether an actual close attempt is necessary...
if (this.active.get() && this.closed.compareAndSet(false, true)) {
 /*********省略其他代码***********/
// Destroy all cached singletons in the context's BeanFactory.
destroyBeans();
 		/*********省略其他代码***********/
}
}
1
2
3
4
5
6
7
8
9

在AbstractApplicationContext类的doClose()方法中,会调用destroyBeans()方法销毁所有的单例Bean。

(4)解析AbstractApplicationContext类的destroyBeans()方法

protected void destroyBeans() {
getBeanFactory().destroySingletons();
}
1
2
3

在AbstractApplicationContext类的destroyBeans()方法中,调用了beanFactory的destroySingletons()方法来销毁单例Bean。

(5)解析DefaultListableBeanFactory类的destroySingletons()方法

@Override
public void destroySingletons() {
super.destroySingletons();
/*********省略其他代码***********/
}
1
2
3
4
5

在DefaultListableBeanFactory类的destroySingletons()方法中,会调用父类的destroySingletons()方法。

(6)解析DefaultSingletonBeanRegistry类的destroySingletons()方法

public void destroySingletons() {
/*********省略其他代码***********/
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
}
	/*********省略其他代码***********/
}
1
2
3
4
5
6
7

在DefaultSingletonBeanRegistry类的destroySingletons()方法中,会调用destroySingleton()方法销毁指定的单例Bean对象。

(7)解析DefaultListableBeanFactory类的destroySingleton(String beanName)方法

@Override
public void destroySingleton(String beanName) {
super.destroySingleton(beanName);
/*********省略其他代码***********/
}
1
2
3
4
5

在DefaultListableBeanFactory类的destroySingleton()方法中,会调用父类的destroySingleton()方法销毁指定的单例Bean。

(8)解析DefaultSingletonBeanRegistry类的destroySingleton(String beanName)方法

public void destroySingleton(String beanName) {
removeSingleton(beanName);
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
}
destroyBean(beanName, disposableBean);
}
1
2
3
4
5
6
7
8

在DefaultSingletonBeanRegistry类的destroySingleton(方法中,会调用destroyBean()方法来销毁指定的单例Bean对象。

(9)解析DefaultSingletonBeanRegistry类的destroyBean(String beanName, @Nullable DisposableBean bean)方法。

protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
/***********省略其他代码***********/
if (bean != null) {
try {
bean.destroy();
}
catch (Throwable ex) {
/***********省略其他代码***********/
}
}
/***********省略其他代码***********/
}
1
2
3
4
5
6
7
8
9
10
11
12

在DefaultSingletonBeanRegistry类的destroyBean()方法中,会调用bean对象的destroy()方法销毁Bean对象。

(10)解析DisposableBeanAdapter类的destroy()方法

@Override
public void destroy() {
/***********省略其他代码***********/
else if (this.destroyMethods != null) {
for (Method destroyMethod : this.destroyMethods) {
invokeCustomDestroyMethod(destroyMethod);
}
}
/***********省略其他代码***********/
}
1
2
3
4
5
6
7
8
9
10

在DisposableBeanAdapter类的destroy()方法中,会调用invokeCustomDestroyMethod()方法执行自定义的销毁方法。

(11)解析DisposableBeanAdapter类的invokeCustomDestroyMethod(Method destroyMethod)方法

private void invokeCustomDestroyMethod(Method destroyMethod) {
/***********省略其他代码***********/
try {
ReflectionUtils.makeAccessible(destroyMethod);
destroyMethod.invoke(this.bean, args);
} catch (InvocationTargetException ex) {
/***********省略其他代码***********/
} catch (Throwable ex) {
/***********省略其他代码***********/
}
}
1
2
3
4
5
6
7
8
9
10
11

在DisposableBeanAdapter类的invokeCustomDestroyMethod()中,最终会通过Java的反射技术调用自定义的销毁方法。在本章的案例程序中,最终会调用User类的destroy()方法。

# 思考

# 1. @Bean注解为何也是先将Bean定义信息注册到IOC容器中呢?这样做的好处是什么?

为什么注册到IOC容器:

@Bean 注解用于在配置类中声明一个Bean,并将其注册到Spring的IOC容器中。这样做的目的是为了管理Bean的生命周期,包括创建、配置、装配和销毁。将Bean定义信息(如Bean的类型、依赖、作用域等)先注册到IOC容器中,而不是立即实例化,是为了实现依赖注入(DI)和控制反转(IoC)的核心理念。

好处:

  1. 延迟实例化:只有当Bean真正被需要时,Spring容器才会去实例化它。这有助于减少启动时间,因为不是所有的Bean在应用程序启动时都需要被创建。
  2. 依赖注入:Spring容器能够管理Bean之间的依赖关系,并在需要时注入依赖。通过将Bean定义注册到容器中,Spring可以自动解决这些依赖关系。
  3. 生命周期管理:Spring容器可以管理Bean的整个生命周期,包括初始化(通过initMethod)、使用和销毁(通过destroyMethod)。
  4. 灵活性:将Bean定义与Bean的实例化分离,增加了配置的灵活性。例如,可以通过配置更改Bean的作用域、生命周期回调等,而无需修改Bean的实现代码。

# 2. @Bean注解标注的方法被Spring解析后将Bean定义信息注册到IOC容器中后,何时会对注册的信息进行实例化呢?实例化的流程是怎样的?

实例化时机:

Bean的实例化发生在它被请求时,通常是在依赖注入时。具体来说,当一个Bean被另一个Bean依赖并请求时,Spring容器会检查该Bean是否已实例化;如果没有,则进行实例化。

实例化流程:

  1. Bean的查找:当一个Bean被请求时,Spring容器首先会在容器中查找该Bean的定义。
  2. Bean的实例化:如果找到了Bean的定义但Bean尚未实例化,Spring容器会根据Bean的定义(如通过构造函数、工厂方法或静态工厂方法等)来实例化Bean。
  3. 依赖注入:在Bean实例化后,Spring容器会检查Bean的依赖关系,并将依赖的Bean注入到当前Bean中。
  4. Bean的初始化:在依赖注入完成后,Spring容器会调用Bean的初始化方法(如果有的话),这通常是通过Bean定义中的initMethod属性指定的。
  5. Bean的可用:完成上述步骤后,Bean就准备好被应用程序使用了。

# 3. Spring是如何调用@Bean注解中使用initMethod和destroyMethod属性指定的方法的?调用的流程是怎样的呢?

initMethod和destroyMethod的调用:

initMethod的调用流程:

  1. 在Bean实例化并完成依赖注入后,Spring容器会检查Bean定义中是否指定了initMethod。
  2. 如果指定了,Spring容器会调用该Bean的initMethod指定的方法,进行初始化操作。

destroyMethod的调用流程:

  1. 当Spring容器关闭时(例如,应用程序停止时),它会开始销毁容器中的Bean。
  2. 对于需要销毁的Bean,Spring容器会检查Bean定义中是否指定了destroyMethod。
  3. 如果指定了,Spring容器会在Bean销毁前调用destroyMethod指定的方法,进行清理操作。

注意:destroyMethod的调用通常发生在Spring容器关闭时,而不是Bean的实例化过程中。此外,对于单例(Singleton)Bean,它们的destroyMethod通常只会在容器关闭时被调用一次。而对于其他作用域的Bean(如请求作用域、会话作用域等),它们的生命周期管理可能更加复杂,但基本的initMethod和destroyMethod调用流程是相似的。

# 1.4 从IOC容器中获取Bean的过程

如果是单实例Bean,则IOC容器启动时,就会创建Bean对象,IOC容器关闭时,销毁Bean对象。如果是多实例Bean,IOC容器在启动时,不会创建Bean对象,在每次从IOC容器中获取Bean对象时,都会创建新的Bean对象返回,IOC容器关闭时,也不会销毁对象。也就是说,如果是多实例Bean,IOC容器不会管理Bean对象。

# 源码时序图

图4-1

图4-2

# 源码解析

从IOC容器中获取Bean的过程的源码执行流程,结合源码执行的时序图,会理解的更加深刻。

(1)在BeanTest类的main()方法中调用了AnnotationConfigApplicationContext类的构造方法,并传入了ComponentScanConfig类的Class对象来创建IOC容器。接下来进入AnnotationConfigApplicationContext类的构造方法。

(2)解析AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class<?>... componentClasses)构造方法

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
1
2
3
4
5

(3)解析AbstractApplicationContext类的refresh()方法

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//############省略其他代码##############
try {
//############省略其他代码##############
invokeBeanFactoryPostProcessors(beanFactory);
   //############省略其他代码##############
}catch (BeansException ex) {
//############省略其他代码##############
}finally {
//############省略其他代码##############
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

(4)解析AbstractApplicationContext类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)方法

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
1
2
3
4
5
6
7

(5)解析PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors)方法

public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

//############省略其他代码##############
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

// 首先,调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 如果bean的名称匹配PriorityOrdered类型
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 将该bean添加到当前注册的处理器列表中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 将已处理的bean的名称添加到已处理bean列表中
processedBeans.add(ppName);
}
}
// 对当前注册的处理器列表进行排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 将当前注册的处理器列表添加到最终的处理器列表中
registryProcessors.addAll(currentRegistryProcessors);
// 调用当前注册的处理器列表中的BeanDefinitionRegistryPostProcessor
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
// 清空当前注册的处理器列表
currentRegistryProcessors.clear();

// 接下来,调用实现了Ordered接口的BeanDefinitionRegistryPostProcessor
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 如果bean的名称不在已处理bean列表中,并且匹配Ordered类型
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
// 将该bean添加到当前注册的处理器列表中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 将已处理的bean的名称添加到已处理bean列表中
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();

// 最后,循环调用所有其他未处理的BeanDefinitionRegistryPostProcessors,直到没有新的出现
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
// 获取所有BeanDefinitionRegistryPostProcessor类型的bean名称
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 如果该bean名称不在已处理bean列表中
if (!processedBeans.contains(ppName)) {
// 将该bean添加到当前注册的处理器列表中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 将该bean名称添加到已处理bean列表中
processedBeans.add(ppName);
// 设置需要再次循环的标志为true
reiterate = true;
}
}
// 对当前注册的处理器列表进行排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 将当前注册的处理器列表添加到最终的处理器列表中
registryProcessors.addAll(currentRegistryProcessors);
// 调用当前注册的处理器列表中的BeanDefinitionRegistryPostProcessor
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
// 清空当前注册的处理器列表
currentRegistryProcessors.clear();
}
//############省略其他代码##############
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

(6)解析AbstractBeanFactory类的getBean(String name, Class requiredType)方法

@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
1
2
3
4

(7)解析AbstractBeanFactory类的doGetBean(String name, Class requiredType, Object[] args, boolean typeCheckOnly)方法

protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {

String beanName = transformedBeanName(name);
Object beanInstance;

// 立即检查单例缓存中是否存在手动注册的单例对象。
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
// 如果bean正在创建中,记录日志信息,表示返回的是一个还未完全初始化的单例对象,是循环引用的结果。
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
 "' that is not fully initialized yet - a consequence of a circular reference");
}
else {
// 如果bean已经创建完成,记录日志信息,表示返回的是一个已缓存的单例对象。
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 获取缓存的单例对象实例,并将其转换为合适的Bean实例。
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果已经在创建这个bean实例,则抛出异常:
// 假设我们在一个循环引用中。
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

// 检查该工厂中是否存在bean定义。
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 未找到 -> 检查父工厂。
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory abf) {
// 委托给父工厂,并调用doGetBean方法获取bean。
// Delegation to parent with explicit doGetBean call.
return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// 委托给父工厂,并传入明确的参数获取bean。
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// 没有参数 -> 委托给父工厂的标准getBean方法获取bean。
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
// 直接委托给父工厂获取bean。
return (T) parentBeanFactory.getBean(nameToLookup);
}
}

if (!typeCheckOnly) {
// 如果不是仅进行类型检查
markBeanAsCreated(beanName);
// 标记bean为已创建
}
// 开始记录bean创建过程
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
// 如果requiredType不为空,则记录bean的类型信息
beanCreation.tag("beanType", requiredType::toString);
}

// 获取合并后的本地Bean定义
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查合并后的Bean定义
checkMergedBeanDefinition(mbd, beanName, args);

// 保证当前Bean所依赖的Bean已经初始化完成
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 如果存在循环依赖关系,则抛出异常
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注册依赖关系
registerDependentBean(dep, beanName);
try {
// 获取依赖的Bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
// 如果找不到依赖的Bean,则抛出异常
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}

// 创建bean实例
// Create bean instance.
if (mbd.isSingleton()) {
// 获取单例缓存中的bean实例,如果不存在则调用lambda表达式创建
sharedInstance = getSingleton(beanName, () -> {
try {
// 调用createBean方法创建bean实例
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// 如果创建过程中发生异常,则从单例缓存中显式移除实例
// 它可能在创建过程中被急切地放入单例缓存中,以允许解决循环引用
// 同时移除任何接收到对该bean的临时引用的bean
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
// 将共享的bean实例转换为适当的Bean实例对象
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// 如果Bean是单例模式,则创建一个新的实例
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
// 在创建原型实例之前进行预处理
beforePrototypeCreation(beanName);
// 创建原型实例
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 在创建原型实例之后进行后处理
afterPrototypeCreation(beanName);
}
// 将原型实例转换为合适的Bean实例对象
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
// 获取Bean的作用域名称
String scopeName = mbd.getScope();
// 如果作用域名称为空
if (!StringUtils.hasLength(scopeName)) {
// 抛出异常,提示未定义Bean的作用域名称
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
// 根据作用域名称获取对应的作用域对象
Scope scope = this.scopes.get(scopeName);
// 如果作用域对象为null
if (scope == null) {
// 抛出异常,提示未注册对应的作用域
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
// 调用作用域对象的get方法获取Bean的实例,并传入Lambda表达式作为参数
Object scopedInstance = scope.get(beanName, () -> {
// 在创建原型Bean之前执行的逻辑
beforePrototypeCreation(beanName);
try {
// 调用createBean方法创建Bean实例
return createBean(beanName, mbd, args);
}
finally {
// 在创建原型Bean之后执行的逻辑
afterPrototypeCreation(beanName);
}
});
// 将作用域Bean实例转换为合适的Bean实例对象
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
// 捕获异常,并转换为ScopeNotActiveException异常抛出
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
// 添加异常类型标签
beanCreation.tag("exception", ex.getClass().toString());
// 添加异常信息标签
beanCreation.tag("message", String.valueOf(ex.getMessage()));
// 清理Bean创建失败后的资源
cleanupAfterBeanCreationFailure(beanName);
// 抛出异常
throw ex;
}
finally {
beanCreation.end();
}
}
// 调用adaptBeanInstance方法,将beanInstance适配为所需类型并返回
return adaptBeanInstance(name, beanInstance, requiredType);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200

doGetBean()方法的源码大体流程:

  • 先通过transformedBeanName()方法转换bean的名称,可能是FactoryBean的名称(&开头),需要转成不带&开头的名称,如果有别名,再获取别名。
  • 从缓存中获取bean,这里的缓存分为一二三级缓存,也就是spring的三级缓存。
  • 根据获取到的对象再去获取想要的Bean,因为这里获取到的对象可能是需要的Bean,也可能是FactoryBean(工厂Bean)。
  • 如果缓存中没有,就去创建Bean对象。
  • 查看有没有父类的BeanFactory,如果有,那么就使用父类去创建Bean对象。
  • 获取要创建的Bean对象的@DependsOn注解上的名称,先去创建DependsOn的Bean,并且校验是否存在循环引用。
  • 创建Bean,根据类型创建不同的Bean,比如singleton,prototype,request,session等。
  • 如果需要转换类型,则进行类型转换。如果不需要转换类型,就不转换类型。

(8)解析DefaultSingletonBeanRegistry类的getSingleton(String beanName)方法

@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
1
2
3
4
5

(9)解析DefaultSingletonBeanRegistry类的getSingleton(String beanName, boolean allowEarlyReference)方法

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 快速检查是否存在实例,无需获取完整的单例锁
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 尝试从早期单例对象中获取实例
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// 在完整的单例锁下,一致地创建早期引用
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 尝试从单例工厂中获取实例
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// 将实例放入早期单例对象中
this.earlySingletonObjects.put(beanName, singletonObject);
// 从单例工厂中移除对应的工厂
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

Spring的三级缓存。

  • singletonObjects:一级缓存,实例化的Bean都会存储在这个Map集合中。
  • earlySingletonObjects:二级缓存,存放未完成的bean的缓存,如果有代理的话,存放的是代理对象。
  • singletonFactories:三级缓存,存放的是一个ObjectFactory,数据通过getObject方法获得。

(10)解析AbstractBeanFactory类的getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd)方法。

protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
//name是否是以&开头
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
	//如果bean不是FactoryBean,直接返回beanInstance
if (!(beanInstance instanceof FactoryBean<?> factoryBean)) {
return beanInstance;
}

Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
// 尝试从缓存中获取FactoryBean创建的bean实例//从缓存中获取对象
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// 从工厂返回bean实例
// 如果bean是单例的,则将FactoryBean创建的bean实例缓存起来
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
//通过FactoryBean获取需要的beanInstance
object = getObjectFromFactoryBean(factoryBean, beanName, !synthetic);
}
return object;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

整个getObjectForBeanInstance()方法大体的流程:

  • 首先判断name是不是FactoryBean的name,也就是&开头的name,如果beanInstance不是FactoryBean则抛异常。

  • 如果name是FactoryBeanName,那么需要获取的就是FactoryBean,直接返回对象。

  • 如果都没有返回,那么已经可以确定此时已经可以确定beanInstance是FactoryBean了,因为如果不是FactoryBean在(beanInstance instanceof FactoryBean)就已经返回了。

  • 通过FactoryBean的getObject方法获取需要的Bean实例。

(11)解析DefaultSingletonBeanRegistry类的getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法。

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
// 从单例缓存中获取指定beanName的单例对象
Object singletonObject = this.singletonObjects.get(beanName);
// 如果单例对象为空
if (singletonObject == null) {
// 如果当前有单例对象正在销毁
if (this.singletonsCurrentlyInDestruction) {
//#########省略异常代码################
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// 记录是否需要记录被抑制的异常
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 通过工厂对象获取单例对象
singletonObject = singletonFactory.getObject();
// 设置标志位,表示创建了新的单例对象
newSingleton = true;
}
catch (IllegalStateException ex) {
// 如果在获取单例对象的过程中出现了IllegalStateException异常,
// 则尝试从已存在的单例对象集合中获取单例对象
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
// 如果需要记录被抑制的异常,则将已记录的异常添加到BeanCreationException中
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
// 清空已记录的异常集合
this.suppressedExceptions = null;
}
// 调用afterSingletonCreation方法,执行单例对象创建后的操作
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 如果创建了新的单例对象,则将其添加到单例对象集合中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

在上述getSingleton()方法中,创建Bean对象之前调用了 beforeSingletonCreation()方法,在创建对象之后调用了afterSingletonCreation()方法。源码如下:

protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}

protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
1
2
3
4
5
6
7
8
9
10
11

(12)回到AbstractBeanFactory类的doGetBean(String name, Class requiredType, Object[] args, boolean typeCheckOnly)方法

if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
1
2
3
4
5
6
7
8
9
10
11
12

(13)解析AbstractAutowireCapableBeanFactory类的createBean(String beanName, RootBeanDefinition mbd, Object[] args)方法

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
	//##############省略其他代码############
		try {
			// 创建bean实例
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			// 如果开启了trace级别的日志
			if (logger.isTraceEnabled()) {
				// 输出创建bean实例完成的日志
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			// 返回bean实例
			return beanInstance;
		}
   //##############省略其他代码############
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在createBean()方法中,只是做了一些准备工作,并没有真正的创建Bean对象,真正创建Bean对象是在doCreateBean()方法中完成的。

(14)解析AbstractAutowireCapableBeanFactory类的doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args)方法

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {

// 实例化bean
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
// 如果bean是单例的
if (mbd.isSingleton()) {
// 从factoryBeanInstanceCache中移除bean的实例包装器
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
// 如果实例包装器为空
if (instanceWrapper == null) {
// 创建bean的实例包装器
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 获取bean的实例
Object bean = instanceWrapper.getWrappedInstance();
// 获取bean的类型
Class<?> beanType = instanceWrapper.getWrappedClass();
// 如果bean的类型不是NullBean类
if (beanType != NullBean.class) {
// 设置解析后的目标类型
mbd.resolvedTargetType = beanType;
}

// 允许后处理器修改合并后的bean定义
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 应用合并后的bean定义后处理器
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
// 合并后的bean定义后处理失败
"Post-processing of merged bean definition failed", ex);
}
// 标记为已后处理
mbd.markAsPostProcessed();
}
}

// 提前缓存单例对象,以便能够解决由生命周期接口(如BeanFactoryAware)触发的循环引用问题
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
  isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// 如果允许提前暴露单例对象
if (logger.isTraceEnabled()) {
// 输出日志,表示正在提前缓存bean对象以解析潜在的循环引用问题
logger.trace("Eagerly caching bean '" + beanName +
 "' to allow for resolving potential circular references");
}
// 将beanName和获取早期bean引用的lambda表达式添加到单例工厂中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

// 初始化bean实例
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 为bean填充属性
populateBean(beanName, mbd, instanceWrapper);
// 初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
// 如果异常是BeanCreationException且异常中的beanName与当前beanName相同
if (ex instanceof BeanCreationException bce && beanName.equals(bce.getBeanName())) {
// 抛出该异常
throw bce;
}
else {
// 否则,将异常封装为BeanCreationException并抛出
throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex);
}
}

if (earlySingletonExposure) {
// 获取早期单例对象的引用
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
// 如果当前暴露的对象和原始的bean相同,则更新暴露对象为早期单例对象引用
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
// 获取依赖当前bean的其他bean的名称
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
// 如果依赖的bean不是仅用于类型检查的,则添加到实际依赖的bean集合中
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
// 如果存在实际依赖的bean,则抛出异常,表示循环依赖的问题
// 省略异常信息
}
}
}
}


// 注册bean为可销毁的bean
// Register bean as disposable.
try {
// 如果需要,将bean注册为可销毁的bean
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
// 抛出BeanCreationException异常,包含资源描述、bean名称、错误信息以及原始异常
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
// 返回暴露的对象
return exposedObject;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121

doCreateBean()方法的逻辑大体的流程如下:

  • 调用createBeanInstance()方法创建bean。

  • 调用属于applyMergedBeanDefinitionPostProcessors()方法。对Bean进行一些处理。

  • 将bean加入到三级缓存中。

  • 填充Bean需要注入的其他Bean对象。

  • 调用初始化方法,先去调用@PostConstruct注解方法,然后调用InitializingBean的afterPropertiesSet,以及自定义的init-method方法。在Bean调用初始化方法之后,再去调用后置处理器接口检测是否需要生成Aop代理。

  • 接着进行校验。如果从二级缓存能取到,那就说明之前已经从三级缓存获取过。可能是因为循环依赖,也可能是因为别的地方调用了getBean方法。从三级缓存获取时有个getEarlyBeanReference()的方法,就是查看是否要生成代理的bean。如果已经生成代理的Bean,那么在调用初始化方法时,就不会在生成代理Bean了。这样满足exposedObject ==bean,直接只用代理返回。

  • 如果exposedObject和bean不相等:这里的情况就是:如果是spring的@Async注解,在从二级缓存生成代理之后,再去调用初始化方法时,一样会生成代理。所以此时exposedObject不等于bean,再往下发现有循环调用,并且Bean还在创建时,就会抛出异常。

# 思考

# 1.Spring为何会有循环依赖的问题?

Spring的循环依赖问题指的是两个或多个Bean在创建过程中互相引用对方,形成了一个闭环,导致无法完成创建。这种情况通常发生在属性注入的情况下。例如,A类依赖B类,B类又依赖A类。在Spring容器初始化时,如果按顺序创建这两个Bean,当创建A时需要注入B,而B还未创建完成,因为B又需要A,这就形成了一个循环依赖。

# 2.Spring如何解决循环依赖问题?

Spring通过使用三级缓存来解决循环依赖问题:

  1. 一级缓存(singletonObjects):存放已经初始化完成的Bean。
  2. 二级缓存(earlySingletonObjects):存放早期的Bean引用,即已经实例化但未初始化的Bean。
  3. 三级缓存(singletonFactories):存放能够生成Bean的工厂对象。

当A类创建时,首先将其工厂对象放入三级缓存,在实例化A后,将A的早期引用放入二级缓存,并从三级缓存中移除其工厂对象。当A需要注入B时,发现B还未创建,就去创建B。B在创建过程中需要A,这时就可以从二级缓存中获取A的早期引用注入B,从而打破了循环依赖。

# 3.Spring为何使用三级缓存解决循环依赖问题?使用二级缓存不行吗?为什么?

使用二级缓存在某些情况下可能无法解决循环依赖问题,特别是涉及到AOP时。三级缓存中存放的是Bean工厂对象,这个工厂能够生成代理对象。如果只有二级缓存,那么当A类需要被代理时(比如使用了@Transactional注解),在注入B类时就直接注入了A的原始对象,而不是代理对象,这会导致AOP功能失效。三级缓存确保了即使在循环依赖的情况下,也能返回正确的代理对象。当B类尝试获取A类时,可以从三级缓存中得到一个工厂对象,这个工厂在必要时能够生成A的代理,保证了AOP能够正常工作。

# 1.5 @Import注解

@Import注解可以将第三方包中的类对象注入到IOC容器中。Spring底层大量使用了@Import注解来向IOC容器中注入Bean对象。

@Import注解只能标注到类或其他注解上,通常与配置类一起使用的,使用此注解引入的类上可以不再使用@Configuration,@Component等注解标注。

# 注解源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
	Class<?>[] value();
}
1
2
3
4
5
6
  • value:Class数组类型,用于指定其他配置类的字节码,支持指定多个配置类。另外value属性指定的必须是普通类、实现了ImportSelector接口的类和实现了ImportBeanDefinitionRegistrar接口的类。

注意:@Import注解只能标注到类上。

# 源码时序图

图5-1

图5-2

图5-3

# 源码解析

(1)运行ImportTest类的main()方法中,调用了AnnotationConfigApplicationContext类的构造方法,并传入了ImportConfig类的Class对象来创建IOC容器。接下来,会进入AnnotationConfigApplicationContext类的构造方法。

(2)解析AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class<?>... componentClasses)构造方法

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
1
2
3
4
5

(3)解析AbstractApplicationContext类的refresh()方法

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//############省略其他代码##############
try {
//############省略其他代码##############
invokeBeanFactoryPostProcessors(beanFactory);
   //############省略其他代码##############
}catch (BeansException ex) {
//############省略其他代码##############
}finally {
//############省略其他代码##############
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

(4)解析AbstractApplicationContext类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)方法

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
1
2
3
4
5
6
7

(5)解析PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors)方法

核心的逻辑如下:

public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

//############省略其他代码##############
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();

// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();

// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
}
//############省略其他代码##############
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

(6)解析PostProcessorRegistrationDelegate类的invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup)方法

private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {

for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
.tag("postProcessor", postProcessor::toString);
postProcessor.postProcessBeanDefinitionRegistry(registry);
postProcessBeanDefRegistry.end();
}
}
1
2
3
4
5
6
7
8
9
10

(7)解析ConfigurationClassPostProcessor类的postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
	//##########省略其他代码###################
processConfigBeanDefinitions(registry);
}
1
2
3
4
5

(8)解析ConfigurationClassPostProcessor类的processConfigBeanDefinitions(BeanDefinitionRegistry registry)方法

重点逻辑如下:

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
//############省略其他代码#################
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);

Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
parser.parse(candidates);
parser.validate();
//############省略其他代码#################
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
//############省略其他代码#################
}
while (!candidates.isEmpty());
//############省略其他代码#################
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

在processConfigBeanDefinitions()方法中,创建了一个ConfigurationClassParser类型的对象parser,并且调用了parser的parse()方法来解析类的配置信息。

(9)解析ConfigurationClassParser类的parse(Set configCandidates)方法

public void parse(Set<BeanDefinitionHolder> configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
//###############省略其他代码###############
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
this.deferredImportSelectorHandler.process();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

(10)解析ConfigurationClassParser类的parse(AnnotationMetadata metadata, String beanName)方法

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}
1
2
3

(11)解析ConfigurationClassParser类的processConfigurationClass(ConfigurationClass configClass, Predicate filter)方法

protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
//###############省略其他代码####################
SourceClass sourceClass = asSourceClass(configClass, filter);
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
while (sourceClass != null);
this.configurationClasses.put(configClass, configClass);
}
1
2
3
4
5
6
7
8
9

在processConfigurationClass()方法中,会通过do-while()循环获取配置类和其父类的注解信息,SourceClass类中会封装配置类上注解的详细信息。

(12)解析ConfigurationClassParser类的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)方法

重点代码片段如下:

protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
	 //#############省略其他代码#############
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
//#############省略其他代码#############
// No superclass -> processing is complete
return null;
}
1
2
3
4
5
6
7
8
9
10

在doProcessConfigurationClass()方法中,会调用processImports()方法来解析@Import注解。

(13)解析ConfigurationClassParser类的processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection importCandidates, Predicate exclusionFilter, boolean checkForCircularImports)方法。

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
boolean checkForCircularImports) {
	//################省略其他代码#################
this.importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
// 引入的是实现了ImportSelector接口的类
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class, this.environment, this.resourceLoader, this.registry);
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
else {
// 调用ImportSelector接口的selectImports()方法获取要注入到IOC容器中的Bean名称数组
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
}
// 引入的是实现了ImportBeanDefinitionRegistrar接口的类
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
 this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]: " + ex.getMessage(), ex);
}
finally {
this.importStack.pop();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

在processImports()方法中,如果使用@Import注解引入的是实现了ImportSelector接口的类,则执行的是if (candidate.isAssignable(ImportSelector.class))条件的逻辑。如果@Import注解引入的是实现了ImportBeanDefinitionRegistrar接口的类,则执行的是else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class))条件的逻辑,否则执行的是else条件的逻辑。

其中,执行if (selector instanceof DeferredImportSelector) {条件的逻辑时,会调用ImportSelector接口的selectImports()方法获取要注入到IOC容器中的Bean名称数组,如下所示。

String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
1

调用ImportSelector接口的selectImports()方法时,就会调用案例程序中的MyImportSelector类的selectImports()方法。

(14)解析MyImportSelector类的selectImports(AnnotationMetadata importingClassMetadata)方法

@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{ImportSelectorBean.class.getName()};
}
1
2
3
4

在MyImportSelector类的selectImports()方法中,会返回包含ImportSelectorBean类的全类名的String数组,后续会将ImportSelectorBean类的Bean对象注入IOC容器。

(15)回到ConfigurationClassParser类的processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection importCandidates, Predicate exclusionFilter, boolean checkForCircularImports)方法。

如果@Import注解引入的是实现了ImportBeanDefinitionRegistrar接口的类,则执行的是else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class))条件的逻辑,如下所示。

else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class, this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
1
2
3
4
5
6

在上述代码逻辑中会调用configClass的addImportBeanDefinitionRegistrar()方法来添加ImportBeanDefinitionRegistrar对象。

(16)解析ConfigurationClass类的addImportBeanDefinitionRegistrar(ImportBeanDefinitionRegistrar registrar, AnnotationMetadata importingClassMetadata)方法

void addImportBeanDefinitionRegistrar(ImportBeanDefinitionRegistrar registrar, AnnotationMetadata importingClassMetadata) {
this.importBeanDefinitionRegistrars.put(registrar, importingClassMetadata);
}
1
2
3

在addImportBeanDefinitionRegistrar()方法中,会将传入的registrar参数作为Key,importingClassMetadata参数作为Value存储importBeanDefinitionRegistrars结构中。

importBeanDefinitionRegistrars结构的定义如下所示。

private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars = new LinkedHashMap<>();
1

importBeanDefinitionRegistrars是一个LinkedHashMap对象,也就是会将ImportBeanDefinitionRegistrar对象和AnnotationMetadata对象的映射关系存入一个LinkedHashMap对象中。

(17)再次回到ConfigurationClassParser类的processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection importCandidates, Predicate exclusionFilter, boolean checkForCircularImports)方法。

如果@Import注解引入的类既没有实现ImportSelector接口,又没有实现ImportBeanDefinitionRegistrar接口,则执行else逻辑

else {
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
1
2
3
4
5

在else逻辑中,会按照解析@Configuration注解的逻辑执行

其实,在processImports()方法中,如果@Import注解引入的类实现了ImportSelector接口,并且没有实现DeferredImportSelector接口的话,最终还是会执行processImports()方法的else逻辑。

(18)回到ConfigurationClassPostProcessor类的processConfigBeanDefinitions(BeanDefinitionRegistry registry)方法。

在ConfigurationClassPostProcessor类的processConfigBeanDefinitions()方法中,执行完ConfigurationClassParser类的parse()方法后,会执行ConfigurationClassBeanDefinitionReader类的loadBeanDefinitions()方法,如下所示。

this.reader.loadBeanDefinitions(configClasses);
1

(19)解析ConfigurationClassBeanDefinitionReader类的loadBeanDefinitions(Set configurationModel)方法

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
1
2
3
4
5
6

在loadBeanDefinitions()方法中,会循环遍历传入的configurationModel集合,并调用loadBeanDefinitionsForConfigurationClass()方法处理遍历的每个元素。

(20)解析ConfigurationClassBeanDefinitionReader类的loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator)方法

private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
//################省略其他代码######################
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}

loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
1
2
3
4
5
6
7
8
9
10
11
12

在loadBeanDefinitionsForConfigurationClass()方法中,如果@Import注解引入的是普通的类,或者是实现了ImportSelector接口的类,则会执行if (configClass.isImported())条件的逻辑,此时会调用registerBeanDefinitionForImportedConfigurationClass()方法向IOC容器中注入配置类的BeanDefinition信息。

(21)解析ConfigurationClassBeanDefinitionReader类的registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass)方法

private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
//###############省略其他代码#################
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
  this.registry.registerBeanDefinition(definitionHolder.getBeanName(),definitionHolder.getBeanDefinition());
configClass.setBeanName(configBeanName);
	//###############省略其他代码#################
}
1
2
3
4
5
6
7
8

在registerBeanDefinitionForImportedConfigurationClass()方法中会调用DefaultListableBeanFactory类的registerBeanDefinition()方法向IOC容器中注入BeanDefinition信息。最终,会将BeanDefinition信息保存到DefaultListableBeanFactory类的beanDefinitionMap中。

(22)回到ConfigurationClassBeanDefinitionReader类的loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator)方法

如果@Import注解引入的是实现了ImportBeanDefinitionRegistrar接口的类,则在loadBeanDefinitionsForConfigurationClass()方法中调用loadBeanDefinitionsFromRegistrars()方法时,会通过configClass的getImportBeanDefinitionRegistrars()方法获取第(16)步保存信息的LinkedHashMap对象。

(23)解析ConfigurationClass类的getImportBeanDefinitionRegistrars()方法

Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> getImportBeanDefinitionRegistrars() {
return this.importBeanDefinitionRegistrars;
}
1
2
3

(24)再次ConfigurationClassBeanDefinitionReader类的loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator)方法。

在loadBeanDefinitionsForConfigurationClass()会调用loadBeanDefinitionsFromRegistrars()方法从实现了ImportBeanDefinitionRegistrar接口的类中加载Bean定义信息。

(25)解析ConfigurationClassBeanDefinitionReader类的loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars)方法

private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
registrars.forEach((registrar, metadata) -> registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
}
1
2
3

在loadBeanDefinitionsFromRegistrars()方法中,会遍历传入的registrars,并调用每个registrar的registerBeanDefinitions()方法注册BeanDefinition信息。

(26)解析ImportBeanDefinitionRegistrar接口的registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,BeanNameGenerator importBeanNameGenerator)方法

default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,BeanNameGenerator importBeanNameGenerator) {
registerBeanDefinitions(importingClassMetadata, registry);
}
1
2
3

registerBeanDefinitions()方法是ImportBeanDefinitionRegistrar接口的一个默认方法,并在方法中调用了另一个registerBeanDefinitions()方法。其中调用的这个registerBeanDefinitions()方法就是我们自己实现了ImportBeanDefinitionRegistrar接口的类中具体实现的registerBeanDefinitions()方法。

(27)解析MyImportBeanDefinitionRegistrar类的registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)方法

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
String beanName = ImportBeanDefinitionRegistrarBean.class.getName();
BeanDefinition beanDefinition = new RootBeanDefinition(ImportBeanDefinitionRegistrarBean.class);
registry.registerBeanDefinition(beanName, beanDefinition);
}
1
2
3
4
5
6

在registerBeanDefinitions()方法中,最终会调用DefaultListableBeanFactory类的registerBeanDefinition()方法向IOC容器中注入BeanDefinition信息。最终会将BeanDefinition信息保存到DefaultListableBeanFactory类的beanDefinitionMap中。

# 思考

# 1. 在ConfigurationClassParser类的processImports()中,如果@Import注解引入的是普通类或者引入的是实现了ImportSelector接口,并且没有实现DeferredImportSelector接口的类,最终还是会执行processImports()方法的else逻辑。那么最终是如何执行else逻辑的?

当@Import注解引入的是普通类或者引入的是实现了ImportSelector接口且没有实现DeferredImportSelector接口的类时,以下是一般会发生的过程:

  1. processImports()方法会检查通过@Import注解引入的类。
  2. 如果引入的类不是ImportSelector或者ImportBeanDefinitionRegistrar,那么它将被视为一个普通的配置类。
  3. 对于实现了ImportSelector接口的类,如果它没有实现DeferredImportSelector接口,那么它的selectImports()方法会被调用以返回一个字符串数组,这些字符串代表了需要被导入的配置类的名称。
  4. 对于每个通过selectImports()返回的配置类名称,Spring会尝试加载这些类,并递归地调用processImports()方法处理这些新加载的配置类。

# 2. @Import注解的三种案例在Spring底层的源码执行流程分别是什么?

  1. 直接导入配置类:
    • Spring直接解析导入的类,将其视为配置类,并处理其上的注解(如@Bean、@Import等)。
  2. 导入实现了ImportSelector接口的类:
    • 实例化ImportSelector实现类。
    • 调用其selectImports()方法获取要导入的类名或配置类。
    • 对这些类进行解析和处理。
  3. 导入实现了DeferredImportSelector接口的类:
    • 与ImportSelector类似,但DeferredImportSelector允许导入操作被延迟到所有常规的ImportSelector和@Configuration类都被处理之后。
    • 这在需要基于其他Bean的存在性条件导入Bean时特别有用

# 3. 使用@Import注解向IOC容器中注入Bean与使用@Bean注解有什么区别?

  • @Import:用于导入配置类,可以导入一个或多个类,这些类可以包含@Bean注解定义的Bean,或者它们自身是ImportSelector/DeferredImportSelector的实现,用于动态选择Bean的导入。它主要用于模块化和重用配置。
  • @Bean:在配置类中声明一个Bean,并指定其创建逻辑(通过方法)。它允许更细粒度地控制Bean的创建过程,包括依赖注入、初始化等。

# 1.6 @PropertySource注解

@PropertySource注解是Spring中提供的一个通过指定配置文件位置来加载配置文件的注解,并且可以将配置文件中的内容存放到Spring的环境变量中。除了可以通过Spring的环境变量读取配置项之外,还可以通过@Value注解获取配置项的值。另外,Spring中还提供了一个@PropertySources注解,在@PropertySources注解注解中,可以引入多个@PropertySource注解。

# 注解源码

1.@PropertySource注解

@PropertySource注解只能标注到类上,能够通过指定配置文件的位置来加载配置文件,@PropertySource注解除了可以加载properties配置文件外,也可以加载xml配置文件和yml配置文件。如果加载yml配置文件时,可以自定义PropertySourceFactory实现yml配置文件的解析操作。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {
	String name() default "";
	String[] value();
	/**
	 * @since 4.0
	 */
	boolean ignoreResourceNotFound() default false;
	/**
	 * @since 4.3
	 */
	String encoding() default "";
	/**
	 * @since 4.3
	 */
	Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

注解中各个属性的含义如下所示。

  • name:表示加载的资源的名称,如果为空,则会根据加载的配置文件自动生成一个名称。
  • value:表示加载的资源的路径,这个路径可以是类路径,也可以是文件路径。
  • ignoreResourceNotFound:表示当配置文件未找到时,是否忽略文件未找到的错误。默认值为false,也就是说当未找到配置文件时,Spring启动就会报错。
  • encoding:表示解析配置文件使用的字符集编码。
  • factory:表示读取对应配置文件的工厂类,默认的工厂类是PropertySourceFactory。

2.@PropertySources注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PropertySources {
	PropertySource[] value();
}
1
2
3
4
5
6

提供了一个PropertySource数组类型的value属性。@PropertySources注解可引入多个@PropertySource注解。

# 源码时序图

图6-1

图6-2

# 源码解析

(1)运行PropertySourceTest类的main()方法,调用了AnnotationConfigApplicationContext类的构造方法并传入了PropertySourceConfig类的Class对象来创建IOC容器。

@PropertySource注解在Spring源码中的执行流程的(2)~(11)步与@Import注解相同,这里直接跳到ConfigurationClassParser类的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)方法。

(2)解析ConfigurationClassParser类的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)方法

protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
//#############省略其他代码################
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.propertySourceRegistry != null) {
this.propertySourceRegistry.processPropertySource(propertySource);
}
}
	//#############省略其他代码################
}
1
2
3
4
5
6
7
8
9
10
11
12
13

在ConfigurationClassParser类的doProcessConfigurationClass()方法中,遍历获取到的@PropertySources注解和@PropertySource注解的属性,并且调用propertySourceRegistry对象的processPropertySource()方法解析注解属性的值。

(3)解析PropertySourceRegistry类的processPropertySource(AnnotationAttributes propertySource)方法

void processPropertySource(AnnotationAttributes propertySource) throws IOException {
String name = propertySource.getString("name");
if (!StringUtils.hasLength(name)) {
name = null;
}
String encoding = propertySource.getString("encoding");
if (!StringUtils.hasLength(encoding)) {
encoding = null;
}
String[] locations = propertySource.getStringArray("value");
Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
Class<? extends PropertySourceFactory> factorClassToUse = (factoryClass != PropertySourceFactory.class ? factoryClass : null);
PropertySourceDescriptor descriptor = new PropertySourceDescriptor(Arrays.asList(locations), ignoreResourceNotFound, name, factorClassToUse, encoding);
this.propertySourceProcessor.processPropertySource(descriptor);
this.descriptors.add(descriptor);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

在PropertySourceRegistry类的processPropertySource()方法中,解析@PropertySource注解中的属性后,将解析出的属性值封装到PropertySourceDescriptor对象中,调用propertySourceProcessor对象的processPropertySource()方法,并传入PropertySourceDescriptor对象进行进一步处理。

(4)解析PropertySourceProcessor类的processPropertySource(PropertySourceDescriptor descriptor)方法

public void processPropertySource(PropertySourceDescriptor descriptor) throws IOException {
String name = descriptor.name();
String encoding = descriptor.encoding();
List<String> locations = descriptor.locations();
Assert.isTrue(locations.size() > 0, "At least one @PropertySource(value) location is required");
boolean ignoreResourceNotFound = descriptor.ignoreResourceNotFound();
PropertySourceFactory factory = (descriptor.propertySourceFactory() != null ? instantiateClass(descriptor.propertySourceFactory()) : DEFAULT_PROPERTY_SOURCE_FACTORY);
for (String location : locations) {
try {
String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
Resource resource = this.resourceLoader.getResource(resolvedLocation);
addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
}
catch (IllegalArgumentException | FileNotFoundException | UnknownHostException | SocketException ex) {
			//#########省略其他代码################
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

在processPropertySource()方法中,会通过@PropertySource注解的属性值解析出配置文件的内容,并且通过factory对象的createPropertySource()方法来创建PropertySource对象。

(5)解析DefaultPropertySourceFactory类的createPropertySource(String name, EncodedResource resource)方法

@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
return (name != null ? new ResourcePropertySource(name, resource) : new ResourcePropertySource(resource));
}
1
2
3
4

(6)回到PropertySourceProcessor类的processPropertySource(PropertySourceDescriptor descriptor)方法

在PropertySourceProcessor类的processPropertySource()方法中,创建完PropertySource对象后,会调用addPropertySource()方法将获取到的属性值添加到Spring的环境变量中。

(7)解析PropertySourceProcessor类的addPropertySource(PropertySource<?> propertySource)方法

private void addPropertySource(org.springframework.core.env.PropertySource<?> propertySource) {
String name = propertySource.getName();
MutablePropertySources propertySources = this.environment.getPropertySources();
if (this.propertySourceNames.contains(name)) {
org.springframework.core.env.PropertySource<?> existing = propertySources.get(name);
if (existing != null) {
PropertySource<?> newSource = (propertySource instanceof ResourcePropertySource ?((ResourcePropertySource) propertySource).withResourceName() : propertySource);
if (existing instanceof CompositePropertySource) {
((CompositePropertySource) existing).addFirstPropertySource(newSource);
}
else {
if (existing instanceof ResourcePropertySource) {
existing = ((ResourcePropertySource) existing).withResourceName();
}
CompositePropertySource composite = new CompositePropertySource(name);
composite.addPropertySource(newSource);
composite.addPropertySource(existing);
propertySources.replace(name, composite);
}
return;
        }
    }
    if (this.propertySourceNames.isEmpty()) {
        propertySources.addLast(propertySource);
    }
    else {
        String firstProcessed = this.propertySourceNames.get(this.propertySourceNames.size() - 1);
        propertySources.addBefore(firstProcessed, propertySource);
    }
    this.propertySourceNames.add(name);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

在PropertySourceProcessor类的addPropertySource()方法中,会将解析出的配置文件的内容添加到Spring的环境变量中。具体就是在PropertySourceProcessor类的addPropertySource()方法中,获取到ConfigurableEnvironment中的MutablePropertySources对象,用来存储解析出的配置文件中的配置项内容。如果有相同的配置项内容,将existing对象强转为CompositePropertySource类型,把新旧相同的配置项进行合并,再放到MutablePropertySources对象中。后续就可以通过Spring的环境变量,来获取到配置文件中的配置项内容。

# 思考

# 1. @PropertySource注解的执行流程

@PropertySource注解的执行流程主要涉及Spring框架在启动时如何处理和加载配置文件。执行流程:

  1. 配置类扫描:Spring容器在启动时,会扫描所有带有@Configuration、@Component等注解的类,以发现配置信息。
  2. 注解识别:在扫描到的配置类中,Spring会识别@PropertySource注解。该注解用于指定一个或多个属性文件的位置。
  3. 加载配置文件:根据@PropertySource注解中指定的路径(如classpath:config.properties),Spring会尝试加载这些配置文件。如果指定了多个文件,Spring会按照声明的顺序加载它们。
  4. 解析配置文件:加载配置文件后,Spring会解析文件中的配置项,将它们作为键值对存储在内存中。
  5. 添加到环境变量:解析出的配置项会被添加到Spring的环境变量(Environment)中,这样它们就可以在应用程序的任何地方通过占位符(如${app.name})来访问了。
  6. 属性注入:在配置类或其他组件中,可以通过@Value注解将环境变量中的配置项注入到字段、方法参数或构造函数参数中。

# 2. @PropertySource注解是如何将配置文件加载到环境变量的?

@PropertySource注解通过以下步骤将配置文件加载到Spring的环境变量中:

  1. 注解声明:在配置类上使用@PropertySource注解,并指定配置文件的位置。
  2. 配置加载:Spring容器在启动时,会识别并使用PropertySourceLoader(默认是DefaultPropertySourceLoader)来加载@PropertySource注解指定的配置文件。
  3. 解析与存储:加载的配置文件会被解析成一系列的键值对,并作为PropertySource对象存储在Spring的环境变量(ConfigurableEnvironment)中。每个PropertySource对象都有一个唯一的名称,用于区分不同的配置源。
  4. 环境变量集成:最终,这些PropertySource对象会被集成到Spring的环境变量中,使得应用程序可以通过环境变量接口(如Environment接口)来访问这些配置项。

# 3. @PropertySource注解的使用场景

@PropertySource注解的使用场景主要包括以下几个方面:

  1. 配置文件分离:在大型项目中,可能需要将不同的配置项分散到不同的配置文件中,以便于管理和维护。@PropertySource注解允许开发者指定多个配置文件的位置,从而实现配置文件的分离。
  2. 动态配置:在某些情况下,应用程序可能需要根据不同的环境(如开发环境、测试环境、生产环境)来加载不同的配置文件。通过使用@PropertySource注解和Spring的profiles功能,可以轻松实现动态配置。
  3. 外部化配置:将配置项从代码中分离出来,放到外部的配置文件中,可以提高代码的可维护性和可配置性。@PropertySource注解是实现外部化配置的一种有效方式。
  4. 加密配置:对于敏感信息(如数据库密码、API密钥等),可能需要将其加密后存储在配置文件中。通过使用自定义的PropertySourceLoader和加密/解密机制,可以安全地加载和使用这些加密的配置项。

# 1.7 @DependsOn注解

@DependsOn注解是Spring中提供的一个指定Spring创建Bean的依赖顺序的注解。例如,在Spring中需要创建A对象和B对象,可以使用@DependsOn注解指定创建A对象时依赖B对象,此时,在Spring中就会先创建B对象,然后再创建A对象。

# 注解源码

@DependsOn注解可以标注到类或方法上,可以控制bean的创建、初始化和销毁方法的执行顺序。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DependsOn {
	String[] value() default {};
}
1
2
3
4
5
6
  • value:表示指定的Bean的唯一标识,被指定的Bean会在Spring创建当前Bean之前被创建。

# 注解使用场景

@DependsOn注解主要用于指定当前Bean对象所依赖的其他Bean对象。Spring在创建当前Bean之前,会先创建由@DependsOn注解指定的依赖Bean,使用@DependsOn注解的场景通常会有以下几种场景:

(1)在某些情况下,Bean不是通过属性或构造函数参数显式依赖于另一个Bean的,但是却需要在创建一个Bean对象之前,需要先创建另一个Bean对象,此时就可以使用@DependsOn注解。

(2)在单例Bean的情况下@DependsOn既可以指定初始化依赖顺序,也可以指定Bean相应的销毁执行顺序。

(3)@DependsOn注解可标注到任何直接或间接带有@Component注解的Bean或标注到@Bean注解的方法上,可以控制Bean的创建、初始化和销毁方法执行顺序。

(4)观察者模式可以分为事件,事件源和监听器三个组件,如果在Spring中需要实现观察者模式时,就可以使用@DependsOn注解实现监听器的Bean对象在事件源的Bean对象之前被创建。

# 源码时序图

# 注册Bean的源码时序图

图7-1

# 调用Bean工厂后置处理器的源码时序图

图7-2

图7-3

# 创建Bean的源码时序图

图7-5

# 源码解析

# 注册Bean的源码流程

(1)运行DependsOnTest类的main()方法,调用了AnnotationConfigApplicationContext类的构造方法并传入了DependsOnConfig类的Class对象来创建IOC容器。

(2)解析AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class<?>... componentClasses)构造方法

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    this();
    register(componentClasses);
    refresh();
}
1
2
3
4
5

(3)解析AnnotationConfigApplicationContext类的register(Class<?>... componentClasses) 方法

@Override
public void register(Class<?>... componentClasses) {
    /************省略其他代码***************/
    this.reader.register(componentClasses);
    registerComponentClass.end();
}
1
2
3
4
5
6

(4)解析AnnotatedBeanDefinitionReader类的register(Class<?>... componentClasses)方法

public void register(Class<?>... componentClasses) {
    for (Class<?> componentClass : componentClasses) {
        registerBean(componentClass);
    }
}
1
2
3
4
5

在AnnotatedBeanDefinitionReader类的register()方法中,会循环遍历传入的componentClasses数组,并将遍历出的每个componentClass元素作为参数调用registerBean()方法注册Bean。

(5)解析AnnotatedBeanDefinitionReader类的registerBean(Class<?> beanClass)方法

public void registerBean(Class<?> beanClass) {
    doRegisterBean(beanClass, null, null, null, null);
}
1
2
3

(6)解析AnnotatedBeanDefinitionReader类的doRegisterBean(Class beanClass, String name, Class<? extends Annotation>[] qualifiers, Supplier supplier, BeanDefinitionCustomizer[] customizers)方法

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
    /******************省略其他代码**********************/
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    /******************省略其他代码**********************/
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
1
2
3
4
5
6
7
8

(7)解析AnnotationConfigUtils类的processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd)方法

public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
    processCommonDefinitionAnnotations(abd, abd.getMetadata());
}
1
2
3

(8)解析AnnotationConfigUtils类的processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata)方法

static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
    AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
    if (lazy != null) {
        abd.setLazyInit(lazy.getBoolean("value"));
    }
    else if (abd.getMetadata() != metadata) {
        lazy = attributesFor(abd.getMetadata(), Lazy.class);
        if (lazy != null) {
            abd.setLazyInit(lazy.getBoolean("value"));
        }
    }

    if (metadata.isAnnotated(Primary.class.getName())) {
        abd.setPrimary(true);
    }
    AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
    if (dependsOn != null) {
        abd.setDependsOn(dependsOn.getStringArray("value"));
    }

    AnnotationAttributes role = attributesFor(metadata, Role.class);
    if (role != null) {
        abd.setRole(role.getNumber("value").intValue());
    }
    AnnotationAttributes description = attributesFor(metadata, Description.class);
    if (description != null) {
        abd.setDescription(description.getString("value"));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

在processCommonDefinitionAnnotations()方法中解析了@DependsOn注解,并将解析出的@DependsOn注解中的value属性的值设置到AnnotatedBeanDefinition对象的dependsOn属性中。

(9)回到AnnotatedBeanDefinitionReader类的doRegisterBean(Class beanClass, String name, Class<? extends Annotation>[] qualifiers, Supplier supplier, BeanDefinitionCustomizer[] customizers)方法。

在AnnotatedBeanDefinitionReader类的doRegisterBean()方法中,会调用BeanDefinitionReaderUtils类的registerBeanDefinition()方法,并将封装了@DependsOn注解属性的abd对象和beanName封装成BeanDefinitionHolder对象,并且与registry一起作为参数传递给BeanDefinitionReaderUtils类的registerBeanDefinition()方法。

(10)解析BeanDefinitionReaderUtils类的registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法

public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
    String beanName = definitionHolder.getBeanName();
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}
1
2
3
4
5
6
7
8
9
10

(11)解析DefaultListableBeanFactory类的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
	/*********省略其他代码**********/
	BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
	if (existingDefinition != null) {
		/*********省略其他代码**********/
	}
	else {
		/*********省略其他代码**********/
		else {
			// Still in startup registration phase
			this.beanDefinitionMap.put(beanName, beanDefinition);
			this.beanDefinitionNames.add(beanName);
			removeManualSingletonName(beanName);
		}
		this.frozenBeanDefinitionNames = null;
	}
    /*********省略其他代码**********/
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

在DefaultListableBeanFactory类的registerBeanDefinition()方法中,会将beanName为Key,beanDefinition对象作为Value保存到beanDefinitionMap中。

# 调用Bean工厂后置处理器的源码流程

@DependsOn注解在Spring源码层面调用Bean工厂后置处理器的执行流程,执行到ConfigurationClassParser类的doProcessConfigurationClass()方法之前的逻辑与解析@Import注解的代码流程相同,直接从ConfigurationClassParser类的doProcessConfigurationClass()方法开始解析。

(1)解析ConfigurationClassParser类的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)方法

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException {
    /****************省略其他代码****************/
    Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
        sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    if (!componentScans.isEmpty() &&
        !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
        for (AnnotationAttributes componentScan : componentScans) {
            Set<BeanDefinitionHolder> scannedBeanDefinitions =
                this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
            for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                if (bdCand == null) {
                    bdCand = holder.getBeanDefinition();
                }
                if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                    parse(bdCand.getBeanClassName(), holder.getBeanName());
                }
            }
        }
    }
    /****************省略其他代码****************/
    return null;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

在ConfigurationClassParser类的doProcessConfigurationClass()方法中,会调用componentScanParser的parse()方法来解析配置类上的注解。

(2)解析ComponentScanAnnotationParser类的parse(AnnotationAttributes componentScan, String declaringClass)方法

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, String declaringClass) {
    /***********省略其他代码*************/
    return scanner.doScan(StringUtils.toStringArray(basePackages));
}
1
2
3
4

在ComponentScanAnnotationParser类的parse()方法中,会调用scanner对象的doScan()方法扫描@ComponentScan注解中basePackages属性设置的包名。

(3)解析ClassPathBeanDefinitionScanner类中的doScan(String... basePackages)方法

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) {
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        for (BeanDefinition candidate : candidates) {
            /************省略其他代码************/
            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);
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

在ClassPathBeanDefinitionScanner类中的doScan()方法中,会调用AnnotationConfigUtils类的processCommonDefinitionAnnotations()方法来解析注解的信息。

另外,在ClassPathBeanDefinitionScanner类中的doScan()方法中,会调用registerBeanDefinition()方法来注册BeanDefinition信息。

(4)解析ClassPathBeanDefinitionScanner类的registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法

protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
1
2
3

在ClassPathBeanDefinitionScanner类的registerBeanDefinition()方法中,直接调用了BeanDefinitionReaderUtils类的registerBeanDefinition()方法来注册BeanDefinition信息。

(5)解析BeanDefinitionReaderUtils类的registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法

public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {
    String beanName = definitionHolder.getBeanName();
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    /*********省略其他代码************/
}
1
2
3
4
5

在BeanDefinitionReaderUtils类的registerBeanDefinition()方法中,最终就会调用DefaultListableBeanFactory类的registerBeanDefinition()方法来注册BeanDefinition信息。

# 创建Bean的源码流程

@DependsOn注解在Spring源码层面创建Bean的执行流程,执行到AbstractApplicationContext类的refresh()方法的逻辑,与解析@Import注解执行到AbstractApplicationContext类的refresh()方法的逻辑相同

(1)解析AbstractApplicationContext类的refresh()方法

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
       /*********省略其他代码************/
        try {
            /*********省略其他代码************/
            finishBeanFactoryInitialization(beanFactory);
			/*********省略其他代码************/
        }
        catch (BeansException ex) {
            /*********省略其他代码************/
        }
        finally {
            /*********省略其他代码************/
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在refresh()中会调用finishBeanFactoryInitialization()方法来完成非懒加载的单实例Bean的初始化工作。

(2)解析finishBeanFactoryInitialization类的finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory)方法

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    /*******省略其他代码*******/
    beanFactory.preInstantiateSingletons();
}
1
2
3
4

在finishBeanFactoryInitialization类的finishBeanFactoryInitialization()方法中,会调用beanFactory对象的preInstantiateSingletons()方法来初始化所有的非懒加载的单实例Bean。

(3)解析DefaultListableBeanFactory类的preInstantiateSingletons()方法

@Override
public void preInstantiateSingletons() throws BeansException {
    /*********省略其他代码*********/
    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            if (isFactoryBean(beanName)) {
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                if (bean instanceof SmartFactoryBean<?> smartFactoryBean && smartFactoryBean.isEagerInit()) {
                    getBean(beanName);
                }
            }
            else {
                getBean(beanName);
            }
        }
    }
	/*********省略其他代码*********/
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

在DefaultListableBeanFactory类的preInstantiateSingletons()方法中,会遍历beanDefinitionNames集合中所有的beanName,并调用getBean()方法初始化所有非懒加载的单实例Bean。

(4)解析AbstractBeanFactory类的getBean(String name)方法

@Override
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}
1
2
3
4

在AbstractBeanFactory类的getBean()方法中,直接调用了doGetBean()方法来初始化非懒加载的单实例Bean。

(5)解析AbstractBeanFactory类的doGetBean(String name, Class requiredType, Object[] args, boolean typeCheckOnly)方法

源码详见:org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean(String name, Class requiredType, Object[] args, boolean typeCheckOnly)。重点关注如下代码片段。

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
	/*************省略其他代码**************/
	else {
		/*************省略其他代码**************/
		try {
			/*************省略其他代码**************/
			String[] dependsOn = mbd.getDependsOn();
			if (dependsOn != null) {
				for (String dep : dependsOn) {
					if (isDependent(beanName, dep)) {
						throw new BeanCreationException(mbd.getResourceDescription(), beanName,
								"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
					}
					registerDependentBean(dep, beanName);
					try {
						getBean(dep);
					}
					catch (NoSuchBeanDefinitionException ex) {
						throw new BeanCreationException(mbd.getResourceDescription(), beanName,
								"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
					}
				}
			}
			/*************省略其他代码**************/
		}
		catch (BeansException ex) {
			beanCreation.tag("exception", ex.getClass().toString());
			beanCreation.tag("message", String.valueOf(ex.getMessage()));
			cleanupAfterBeanCreationFailure(beanName);
			throw ex;
		}
		finally {
			beanCreation.end();
		}
	}
	return adaptBeanInstance(name, beanInstance, requiredType);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

在AbstractBeanFactory类的doGetBean()方法中,会获取这些被依赖的beanName,按照数组顺序,再调用AbstractBeanFactory类的getBean()方法来优先创建被依赖的Bean,从而达到控制依赖顺序的目的。

# 思考

# 1. @DependsOn注解的作用

@DependsOn注解的作用是用于指定一个bean的依赖关系,确保该bean在Spring容器中的初始化顺序。当一个bean依赖于其他bean的初始化完成时,可以使用@DependsOn注解来声明这种依赖关系。这样,Spring容器在初始化bean时,会先确保所有被@DependsOn注解声明的依赖bean都已经完成初始化,然后再进行当前bean的初始化。

# 2. Bean的循环依赖与@DependsOn注解的关系

Bean的循环依赖指的是两个或多个bean互相依赖,形成一个闭环,导致Spring在实例化这些bean时遇到的问题。具体来说,当尝试初始化一个bean A时,发现它依赖于另一个bean B,而在尝试初始化bean B时,又发现它反过来依赖于bean A,这就构成了一个循环依赖。

@DependsOn注解与Bean循环依赖的关系是:@DependsOn注解并不直接解决循环依赖问题。它主要用于控制bean的初始化顺序,而不是解决循环依赖。实际上,Spring框架通过一种称为“三级缓存”的机制来解决bean的循环依赖问题。这种机制确保了即使在存在循环依赖的情况下,Spring也能够正确地创建和初始化bean。

需要注意的是,虽然@DependsOn注解可以用于显式地声明bean之间的依赖关系,但如果错误地用于解决循环依赖(例如,两个bean互相使用@DependsOn注解声明对方为依赖),这将会导致Spring无法正确地初始化这些bean,因为它们会陷入一个无限循环的依赖关系中。因此,在实际应用中,应该避免创建循环依赖关系,并考虑通过重新设计类和接口来解决这个问题。

# 1.8 @Conditional注解

@Conditional注解支持按照条件向IOC容器中注册Bean,满足条件的Bean就会被注册到IOC容器中,不满足条件的Bean就不会被注册到IOC容器中。

# 注解源码

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
	Class<? extends Condition>[] value();
}
1
2
3
4
5
6
  • value:指定Condition接口的实现类,Condition接口的实现类中需要编写具体代码实现向Spring中注入Bean的条件。

使用场景:

  • 可以作为类级别的注解直接或者间接的与@Component相关联,包括@Configuration类。
  • 可以作为元注解,用于自动编写构造性注解。
  • 作为方法级别的注解,作用在任何@Bean的方法上。

# 源码时序图

图8-1

图8-2

# 源码解读

(1)解析AnnotatedBeanDefinitionReader类的doRegisterBean(Class beanClass, String name, Class<? extends Annotation>[] qualifiers, Supplier supplier, BeanDefinitionCustomizer[] customizers)方法

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        return;
    }
    abd.setInstanceSupplier(supplier);
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName());
    String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    if (qualifiers != null) {
        for (Class<? extends Annotation> qualifier : qualifiers) {
            if (Primary.class == qualifier) {
                abd.setPrimary(true);
            }
            else if (Lazy.class == qualifier) {
                abd.setLazyInit(true);
            }
            else {
                abd.addQualifier(new AutowireCandidateQualifier(qualifier));
            }
        }
    }
    if (customizers != null) {
        for (BeanDefinitionCustomizer customizer : customizers) {
            customizer.customize(abd);
        }
    }
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

在AnnotatedBeanDefinitionReader类的doRegisterBean()方法中,调用了conditionEvaluator对象的shouldSkip()方法判断是否要忽略当前Bean的注册。

(2)解析ConditionEvaluator类的shouldSkip(AnnotatedTypeMetadata metadata)方法

public boolean shouldSkip(AnnotatedTypeMetadata metadata) {
    return shouldSkip(metadata, null);
}
1
2
3

在ConditionEvaluator类的shouldSkip()方法中,直接调用了另一个重载的shouldSkip()方法。

(3)解析ConditionEvaluator类的shouldSkip(AnnotatedTypeMetadata metadata, ConfigurationPhase phase)方法

public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
    if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
        return false;
    }

    if (phase == null) {
        if (metadata instanceof AnnotationMetadata &&
            ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
            return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
        }
        return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
    }

    List<Condition> conditions = new ArrayList<>();
    for (String[] conditionClasses : getConditionClasses(metadata)) {
        for (String conditionClass : conditionClasses) {
            Condition condition = getCondition(conditionClass, this.context.getClassLoader());
            conditions.add(condition);
        }
    }

    AnnotationAwareOrderComparator.sort(conditions);

    for (Condition condition : conditions) {
        ConfigurationPhase requiredPhase = null;
        if (condition instanceof ConfigurationCondition) {
            requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
        }
        if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
            return true;
        }
    }

    return false;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

在shouldSkip()方法中,首先会判断类或方法上是否标注了@Conditional注解,如果没有标注@Conditional注解,则直接返回false,此时对应的Bean会被创建并注入到IOC容器中。否则,会解析@Conditional注解中的value属性设置的Class对象,将Class对象的全类名解析到conditionClasses数组中,遍历conditionClasses数组中的每个元素生成Condition对象,将Condition对象存入conditions集合中。后续会遍历conditions集合中的每个Condition对象,调用matches()方法,此处的逻辑与matches()方法的返回值正好相反。

  • matches()方法返回false,则此处返回true,表示对应的Bean不会被创建,也不会注入到IOC容器中。
  • matches()方法返回true,则此处返回false,表示对应的Bean会被创建并且会注入到IOC容器中。

后面代码会回到AnnotatedBeanDefinitionReader类的doRegisterBean()方法继续执行后续流程

# 扩展注解

@ConditionalOnBean:仅仅在当前上下文中存在某个对象时,才会实例化一个Bean。

@ConditionalOnClass:某个class位于类路径上,才会实例化一个Bean。

@ConditionalOnExpression:当表达式为true的时候,才会实例化一个Bean。

@ConditionalOnMissingBean:仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean。

@ConditionalOnMissingClass:某个class类路径上不存在的时候,才会实例化一个Bean。

@ConditionalOnNotWebApplication:不是web应用,才会实例化一个Bean。

@ConditionalOnBean:当容器中有指定Bean的条件下进行实例化。

@ConditionalOnMissingBean:当容器里没有指定Bean的条件下进行实例化。

@ConditionalOnClass:当classpath类路径下有指定类的条件下进行实例化。

@ConditionalOnMissingClass:当类路径下没有指定类的条件下进行实例化。

@ConditionalOnWebApplication:当项目是一个Web项目时进行实例化。

@ConditionalOnNotWebApplication:当项目不是一个Web项目时进行实例化。

@ConditionalOnProperty:当指定的属性有指定的值时进行实例化。

@ConditionalOnExpression:基于SpEL表达式的条件判断。

@ConditionalOnJava:当JVM版本为指定的版本范围时触发实例化。

@ConditionalOnResource:当类路径下有指定的资源时触发实例化。

@ConditionalOnJndi:在JNDI存在的条件下触发实例化。

@ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者有多个但是指定了首选的Bean时触发实例化。

# 思考

# 1. @Conditional注解的作用是什么?

@Conditional 注解在Spring框架中用于条件化地创建bean。它允许基于满足特定条件来决定是否创建(或注册)一个bean。这个条件可以是任何形式的逻辑,比如某个类是否存在、某个属性是否被设置等。

# 2. @Conditional注解有哪些使用场景?

  1. 环境特定的配置:根据不同的运行环境(开发、测试、生产)来激活不同的配置bean。
  2. 条件性的依赖注入:只有在某些条件满足时,才注入特定的bean。
  3. 可选的依赖:当某个库或模块可用时,才启用相关的功能或组件。
  4. 功能切换:基于外部配置或环境变量来启用或禁用特定的功能。

# 3. @Conditional注解与@Profile注解有什么区别?

  • 目的不同:@Profile 注解主要用于按环境激活不同的配置,如开发、测试和生产环境。而@Conditional 更通用,可以基于任何条件来决定bean的创建。
  • 灵活性:@Conditional 提供了更高的灵活性,因为它允许你定义自己的条件类,而@Profile 仅基于预定义的环境名称。
  • 使用场景:@Profile 通常用于环境配置,而@Conditional 可以用在任何需要基于条件进行bean注册的场景。

# 4. @Conditional注解在Spring内层的执行流程?

  1. 解析Bean定义:Spring容器在启动时,会解析配置文件或注解中的bean定义。
  2. 检查@Conditional注解:对于带有@Conditional注解的bean定义,Spring会检查这个注解指定的条件类。
  3. 条件评估:Spring会实例化条件类,并调用其matches方法,传入当前的环境(如Environment)和其他相关的bean定义信息。
  4. 注册Bean:如果matches方法返回true,表示条件满足,Spring将会注册这个bean;否则,bean将被忽略。
  5. 依赖注入和Bean初始化:对于满足条件的bean,Spring将进行依赖注入和初始化,使其可供应用程序使用。

# 1.9 @Lazy注解

@Lazy注解可以标注到类、方法、构造方法、参数和属性字段上,能够实现在启动IOC容器时,不创建单例Bean,而是在第一次使用时创建单例Bean对象。

# 注解源码

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Lazy {
	boolean value() default true;
}
1
2
3
4
5
6

value:boolean类型的属性,表示是否延迟创建单例Bean,默认值为true。

  • true:表示延迟创建单例Bean,此时在IOC启动时不会创建Bean对象,而是在第一次使用时创建单例Bean对象。
  • false:表示不延迟创建单例Bean对象,IOC容器启动时,就会创建单例Bean对象。

@Lazy注解只对单例Bean对象起作用,如果使用@Scope注解指定为多例Bean对象,则@Lazy注解将不起作用。

# 源码时序图

# 注册Bean的源码时序图

图9-1

# 调用Bean后置处理器的源码时序图

图9-2

图9-3

图9-4

# 创建单例Bean的源码时序图

图9-5

# 源码解析

# 注册Bean的源码流程

(1)解析AnnotatedBeanDefinitionReader类的doRegisterBean(Class beanClass, String name, Class<? extends Annotation>[] qualifiers, Supplier supplier, BeanDefinitionCustomizer[] customizers)方法

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
	/***********省略其他代码************/
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    if (qualifiers != null) {
        for (Class<? extends Annotation> qualifier : qualifiers) {
            if (Primary.class == qualifier) {
                abd.setPrimary(true);
            }
            else if (Lazy.class == qualifier) {
                abd.setLazyInit(true);
            }
            else {
                abd.addQualifier(new AutowireCandidateQualifier(qualifier));
            }
        }
    }
    /**********省略其他代码************/
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

在AnnotatedBeanDefinitionReader类的doRegisterBean()方法中,调用了AnnotationConfigUtils类的processCommonDefinitionAnnotations()方法。

(2)解析AnnotationConfigUtils类的processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd)方法

public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
    processCommonDefinitionAnnotations(abd, abd.getMetadata());
}
1
2
3

在AnnotationConfigUtils类的processCommonDefinitionAnnotations()方法中,直接调用了另一个重载的processCommonDefinitionAnnotations()方法。

(3)解析AnnotationConfigUtils类的processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata)方法

static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
    AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
    if (lazy != null) {
        abd.setLazyInit(lazy.getBoolean("value"));
    }
    else if (abd.getMetadata() != metadata) {
        lazy = attributesFor(abd.getMetadata(), Lazy.class);
        if (lazy != null) {
            abd.setLazyInit(lazy.getBoolean("value"));
        }
    }
	/**********省略其他代码***********/
}
1
2
3
4
5
6
7
8
9
10
11
12
13

在AnnotationConfigUtils类的processCommonDefinitionAnnotations()方法中,会解析@Lazy注解中的value属性,并将属性值存入abd对象的lazyInit字段中。

(4)回到AnnotatedBeanDefinitionReader类的doRegisterBean(Class beanClass, String name, Class<? extends Annotation>[] qualifiers, Supplier supplier, BeanDefinitionCustomizer[] customizers)方法。

在方法中遍历qualifiers数组,如果Lazy.class的值与遍历出的qualifier对象相等,就会将abd对象的lazyInit字段设置为true。如果abd对象的lazyInit字段为true,则后续在启动IOC容器的过程中,就不会创建单例Bean对象。

# 调用Bean后置处理器的源码流程

(1)解析ComponentScanAnnotationParser类的parse(AnnotationAttributes componentScan, String declaringClass)方法

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, String declaringClass) {
    /**********省略其他代码**********/
    boolean lazyInit = componentScan.getBoolean("lazyInit");
    if (lazyInit) {
        scanner.getBeanDefinitionDefaults().setLazyInit(true);
    }
	/**********省略其他代码**********/
    return scanner.doScan(StringUtils.toStringArray(basePackages));
}
1
2
3
4
5
6
7
8
9

在ComponentScanAnnotationParser类的parse()方法中,会获取componentScan中的lazyInit属性,如果属性的值为true,会将scanner对象中beanDefinitionDefaults对象的lazyInit属性设置为true。

(2)解析AnnotationConfigUtils类的processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata)方法

# 创建单例Bean的源码流程

重点关注如下代码片段。

@Override
public void preInstantiateSingletons() throws BeansException {
    /************省略其他代码**************/
    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            if (isFactoryBean(beanName)) {
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                if (bean instanceof SmartFactoryBean<?> smartFactoryBean && smartFactoryBean.isEagerInit()) {
                    getBean(beanName);
                }
            }
            else {
                getBean(beanName);
            }
        }
    }
	/************省略其他代码**************/
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

在preInstantiateSingletons()方法中,会循环遍历解析出的Bean名称,在循环中,会根据遍历出的Bean名称获取RootBeanDefinition对象。接下来会进行如下判断。

if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    /*************省略其他代码*************/
}
1
2
3

在preInstantiateSingletons()方法中,会判断每次遍历获取出的RootBeanDefinition对象中如果标记的不是抽象类,并且是单实例对象,并且没有设置延迟创建Bean。同时满足这些条件后,参会调用getbean()方法创建对应的Bean对象,并注入到IOC容器中。

# 思考

# 1. @Lazy注解的作用是什么?

@Lazy注解在Spring框架中用于延迟加载Bean,即在Bean首次被请求时才进行实例化,而不是在Spring容器启动时立即创建。这样做的好处是可以提高应用程序的启动速度,减少不必要的资源消耗,特别是对于那些初始化过程复杂或占用资源较多的Bean。

# 2. @Lazy注解有哪些使用场景?

  1. 优化启动时间:当Spring应用中存在大量Bean,并且不是所有Bean都在应用启动时立即需要时,可以使用@Lazy注解来延迟加载那些不是立即需要的Bean,从而加快应用启动速度。
  2. 解决循环依赖:在Spring中,如果两个Bean之间存在循环依赖,且默认情况下Spring容器在启动时会尝试实例化所有Bean,这可能会导致BeanCurrentlyInCreationException异常。通过使用@Lazy注解,可以延迟其中一个Bean的实例化,从而避免循环依赖问题。
  3. 大对象初始化:对于初始化过程复杂或占用大量资源的Bean,使用@Lazy注解可以延迟其加载,以减少启动时间和资源占用。

# 3. @Lazy注解延迟创建Bean是如何实现的?

@Lazy注解通过修改Bean的生命周期管理来实现延迟加载。当Bean被标记为@Lazy时,Spring容器在启动时不会立即创建该Bean的实例,而是会将其标记为延迟加载。当第一次通过Spring容器请求该Bean时,Spring容器才会创建其实例并返回。

具体实现上,Spring框架会在解析Bean定义时检查是否存在@Lazy注解。如果存在,则会在Bean的定义中设置相应的延迟加载标志。当Bean被请求时,Spring容器会检查该Bean是否被标记为延迟加载。如果是,则执行Bean的创建过程;如果不是,则直接从容器中获取已存在的Bean实例。

# 4. @Lazy注解在Spring内部的执行流程?

  1. 解析Bean定义:Spring容器在启动时解析配置文件或注解中的Bean定义,包括检查是否存在@Lazy注解。
  2. 设置延迟加载标志:对于被@Lazy注解标记的Bean,Spring会在其定义中设置延迟加载标志。
  3. 容器启动完成:Spring容器完成所有必要的初始化工作,但不会立即创建被@Lazy注解标记的Bean实例。
  4. Bean请求:当应用程序首次通过Spring容器请求被@Lazy注解标记的Bean时,Spring容器会检查该Bean是否被标记为延迟加载。
  5. Bean创建与返回:如果Bean被标记为延迟加载,Spring容器将创建该Bean的实例,并将其返回给请求者。此后,该Bean的实例将被缓存在Spring容器中,以便后续请求直接获取。

# 1.10 @Component注解

IOC容器在启动时,如果扫描到被标注了@Component注解的类,则会将这些类的类定义信息自动注入IOC容器,并创建这些类的对象。并且@Component注解还有三个衍生注解:@Repository、@Service和@Controller注解

# 注解源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
	String value() default "";
}
1
2
3
4
5
6
7
  • value:用于指定注入容器时Bean的id。如果没有指定Bean的id,默认值为当前类的名称。

@Component注解的三个衍生注解

(1)@Repository注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
	@AliasFor(annotation = Component.class)
	String value() default "";
}
1
2
3
4
5
6
7
8

(2)@Service注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
	@AliasFor(annotation = Component.class)
	String value() default "";

}
1
2
3
4
5
6
7
8
9

(3)@Controller注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
	@AliasFor(annotation = Component.class)
	String value() default "";
}
1
2
3
4
5
6
7
8

# 源码时序图

1

2

3

# 源码解析

(1)解析ConfigurationClassParser类的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)方法

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass,
    Predicate<String> filter) throws IOException {
    if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
        processMemberClasses(configClass, sourceClass, filter);
    }
    /**************省略其他代码****************/
    Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
        sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    if (!componentScans.isEmpty() &&
        !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
        for (AnnotationAttributes componentScan : componentScans) {
            Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan,
                sourceClass.getMetadata().getClassName());
            for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                if (bdCand == null) {
                    bdCand = holder.getBeanDefinition();
                }
                if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                    parse(bdCand.getBeanClassName(), holder.getBeanName());
                }
            }
        }
    }
    /**************省略其他代码****************/
    return null;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

在ConfigurationClassParser类的doProcessConfigurationClass()方法,判断如果是@Component注解(@Repository、@Service和@Controller注解),会调用processMemberClasses()方法处理内部类。

(2)解析ConfigurationClassParser类的processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass,Predicate filter)方法

private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
    throws IOException {
    Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
    /*****************省略其他代码***************/
}
1
2
3
4
5

在processMemberClasses()方法中,会调用sourceClass的getMemberClasses()方法获取SourceClass的集合。

(3)解析SourceClass类的getMemberClasses()方法

public Collection<SourceClass> getMemberClasses() throws IOException {
    Object sourceToProcess = this.source;
    if (sourceToProcess instanceof Class<?> sourceClass) {
        try {
            Class<?>[] declaredClasses = sourceClass.getDeclaredClasses();
            List<SourceClass> members = new ArrayList<>(declaredClasses.length);
            for (Class<?> declaredClass : declaredClasses) {
                members.add(asSourceClass(declaredClass, DEFAULT_EXCLUSION_FILTER));
            }
            return members;
        } catch (NoClassDefFoundError err) {
            sourceToProcess = metadataReaderFactory.getMetadataReader(sourceClass.getName());
        }
    }
    MetadataReader sourceReader = (MetadataReader) sourceToProcess;
    String[] memberClassNames = sourceReader.getClassMetadata().getMemberClassNames();
    List<SourceClass> members = new ArrayList<>(memberClassNames.length);
    for (String memberClassName : memberClassNames) {
        try {
            members.add(asSourceClass(memberClassName, DEFAULT_EXCLUSION_FILTER));
        } catch (IOException ex) {
            if (logger.isDebugEnabled()) {
                logger.debug("Failed to resolve member class [" + memberClassName
                    + "] - not considering it as a configuration class candidate");
            }
        }
    }
    return members;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

getMemberClasses()方法的主要作用就是处理标注了@Component、@Repository、@Service和@Controller注解的类的内部类,因为内部类也有可能会标注这些注解。在getMemberClasses()方法中,利用反射拿到类的内部类,将内部类封装成SourceClass,存放到members集合中并返回。

(4)返回ConfigurationClassParser类的processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass,Predicate filter)方法

重点关注如下代码:

private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
    throws IOException {
    /*******************省略其他代码*****************/
    if (!memberClasses.isEmpty()) {
        List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
        for (SourceClass memberClass : memberClasses) {
            if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata())
                && !memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
                candidates.add(memberClass);
            }
        }
        /*******************省略其他代码*****************/
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

在ConfigurationClassParser类的processMemberClasses()方法中,如果获取到的内部类集合memberClasses不为空,则遍历获取到的memberClasses集合,使用ConfigurationClassUtils类的isConfigurationCandidate()方法判断内部类上是否有需要处理的注解,如果有需要处理的注解,则将类添加到candidates集合中。

(5)解析ConfigurationClassUtils类的isConfigurationCandidate(AnnotationMetadata metadata)方法

static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
    if (metadata.isInterface()) {
        return false;
    }
    for (String indicator : candidateIndicators) {
        if (metadata.isAnnotated(indicator)) {
            return true;
        }
    }
    return hasBeanMethods(metadata);
}
1
2
3
4
5
6
7
8
9
10
11

isConfigurationCandidate()方法的作用主要是判断内部类上面是否有需要处理的注解,具体的判断逻辑是:如果是接口,则直接返回false,如果是@Component(含@Repository、@Service和@Controller)、@ComponentScan、@Import、@ImportResource等注解,则返回true。最后判断方法上是否标注了@Bean注解,如果标注了@Bean注解,则返回true。否则,返回false。

(6)返回ConfigurationClassParser类的processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass,Predicate filter)方法

重点关注如下代码:

private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
    throws IOException {
    /**********省略其他代码**************/
    if (!memberClasses.isEmpty()) {
        /**********省略其他代码**************/
        OrderComparator.sort(candidates);
        for (SourceClass candidate : candidates) {
            if (this.importStack.contains(configClass)) {
                this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
            } else {
                this.importStack.push(configClass);
                try {
                    processConfigurationClass(candidate.asConfigClass(configClass), filter);
                } finally {
                    this.importStack.pop();
                }
            }
        }
    }
}
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

在processMemberClasses()方法中,首先对获取到的内部类进行排序,随后遍历内部类集合,调用candidate的asConfigClass()方法将内部类封装成ConfigurationClass对象。并传入processConfigurationClass()方法中解析内部类的注解信息。

(7)返回ConfigurationClassParser类的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)方法。

Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
1

(8)解析ClassPathBeanDefinitionScanner类的doScan(String... basePackages)方法

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) {
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        /***************省略其他代码*****************/
    }
    return beanDefinitions;
}
1
2
3
4
5
6
7
8
9

在ClassPathBeanDefinitionScanner类的doScan()中,会遍历传入的扫描包路径数组,调用findCandidateComponents()方法加载符合一定条件的BeanDefinition。

(9)解析ClassPathScanningCandidateComponentProvider类的findCandidateComponents(String basePackage)方法

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
    if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
        return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
    } else {
        return scanCandidateComponents(basePackage);
    }
}
1
2
3
4
5
6
7

在findCandidateComponents()方法中,会调用scanCandidateComponents()方法来扫描basePackage包下标注了注解的类。

(10)解析ClassPathScanningCandidateComponentProvider类的scanCandidateComponents(String basePackage)方法

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
    Set<BeanDefinition> candidates = new LinkedHashSet<>();
    try {
        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
            resolveBasePackage(basePackage) + '/' + this.resourcePattern;
        Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
        boolean traceEnabled = logger.isTraceEnabled();
        boolean debugEnabled = logger.isDebugEnabled();
        for (Resource resource : resources) {
            String filename = resource.getFilename();
            if (filename != null && filename.contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
                continue;
            }
            if (traceEnabled) {
                logger.trace("Scanning " + resource);
            }
            try {
                MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                if (isCandidateComponent(metadataReader)) {
                    ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                    sbd.setSource(resource);
                    if (isCandidateComponent(sbd)) {
                        if (debugEnabled) {
                            logger.debug("Identified candidate component class: " + resource);
                        }
                        candidates.add(sbd);
                    }
                    /***************省略其他代码*************/
                }
       catch(FileNotFoundException ex){
                    if (traceEnabled) {
                        logger.trace("Ignored non-readable " + resource + ": " + ex.getMessage());
                    }
                }
       catch(Throwable ex){
                    throw new BeanDefinitionStoreException(
                        "Failed to read candidate component class: " + resource, ex);
                }
            }
        }
   catch(IOException ex){
            throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
        }
        return candidates;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

在ClassPathScanningCandidateComponentProvider类的scanCandidateComponents()方法中,会加载basePackage包路径下的资源,将其封装成ScannedGenericBeanDefinition类的对象,并传入isCandidateComponent()方法中对类进行过滤。符合条件时,会将当前ScannedGenericBeanDefinition类的对象存入candidates集合中,最终返回candidates集合。

(11)解析ClassPathScanningCandidateComponentProvider类的isCandidateComponent(MetadataReader metadataReader)方法

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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

在isCandidateComponent()方法中,首先遍历excludeFilters规则列表,如果匹配到excludeFilters规则,则直接返回false。否则,遍历includeFilters规则,如果匹配到includeFilters规则,则调用isConditionMatch()方法来匹配@Conditional注解的规则。

在IOC容器启动调用AnnotationConfigApplicationContext类的构造方法时,就会对includeFilters规则列表进行初始化。

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("jakarta.annotation.ManagedBean", cl)), false));
        logger.trace("JSR-250 'jakarta.annotation.ManagedBean' found and supported for component scanning");
    } catch (ClassNotFoundException ex) {
        // JSR-250 1.1 API (as included in Jakarta EE) not available - simply skip.
    }
    try {
        this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("jakarta.inject.Named", cl)), false));
        logger.trace("JSR-330 'jakarta.inject.Named' annotation found and supported for component scanning");
    } catch (ClassNotFoundException ex) {
        // JSR-330 API not available - simply skip.
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

在registerDefaultFilters()方法中,默认会将@Component注解封装成AnnotationTypeFilter对象并存入includeFilters规则列表中。

(12)返回ClassPathBeanDefinitionScanner类的doScan(String... basePackages)方法

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) {
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        for (BeanDefinition candidate : candidates) {
            /**********省略其他代码***********/
            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);
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 思考

# 1. @Component注解的作用

当一个类被@Component注解标记后,Spring容器会在启动时自动扫描并实例化这个类,将其注册为Spring上下文中的一个Bean,从而使其能够被Spring的依赖注入(DI)机制所管理。

# 2. @Component注解的使用场景

@Component注解可以用于任何类,但通常用于那些需要被Spring容器管理的组件,如服务层(Service)、数据访问层(DAO)、控制器(Controller)等。这些组件在应用程序中扮演着重要的角色,通过@Component注解,它们可以被Spring容器自动扫描、实例化并注册为Bean,进而实现依赖注入和AOP(面向切面编程)等功能。

# 3. @Component注解是如何将Bean注入到IOC容器的

@Component注解将Bean注入到IOC容器的过程大致可以分为以下几个步骤:

  1. 自动扫描:通过@ComponentScan注解或Spring配置文件中指定的扫描路径,Spring容器会自动扫描这些路径下的类文件。
  2. 注解识别:在扫描过程中,Spring容器会识别出带有@Component注解的类。
  3. Bean定义注册:对于每个被@Component注解标记的类,Spring容器会创建一个BeanDefinition对象,并将其注册到Spring容器中。BeanDefinition对象包含了Bean的元数据信息,如类名、作用域、生命周期回调等。
  4. Bean实例化:在应用程序启动时或Bean被首次请求时,Spring容器会根据BeanDefinition对象中的信息实例化Bean。
  5. 依赖注入:如果Bean之间存在依赖关系,Spring容器会利用依赖注入机制将这些依赖关系注入到Bean中。

# 4. @Component注解在Spring内部的执行流程

@Component注解在Spring内部的执行流程可以概括为以下几个阶段:

  1. 初始化阶段:Spring容器在启动时,会进行一系列的初始化工作,包括设置注解过滤器、配置扫描路径等。
  2. 扫描阶段:根据配置的扫描路径,Spring容器会扫描这些路径下的类文件,并解析出类文件中的注解信息。
  3. 注册阶段:对于带有@Component注解的类,Spring容器会创建BeanDefinition对象,并将其注册到Spring容器中。
  4. 实例化阶段:在应用程序启动时或Bean被首次请求时,Spring容器会根据BeanDefinition对象中的信息实例化Bean。
  5. 依赖注入阶段:如果Bean之间存在依赖关系,Spring容器会利用依赖注入机制将这些依赖关系注入到Bean中。
  6. 使用阶段:完成上述步骤后,Bean就可以被应用程序中的其他部分所使用了。

# 1.11 @Value注解

@Value注解可以向Spring的Bean的属性中注入数据。并且支持Spring的EL表达式,可以通过${} 的方式获取配置文件中的数据。配置文件支持properties、XML、和YML文件。

# 注解源码

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {
	String value();
}
1
2
3
4
5
6
  • value:指定要向Bean的属性中注入的数据,数据可以是配置文件中的配置项,并且支持EL表达式。

# 源码时序图

# 解析并获取@Value修饰的属性

11.1

11.2

# 为@Value修饰的属性赋值

11.3

11.4

# 使用@Value获取属性的值

11.5

11.6

11.7

# 源码解析

# 解析并获取@Value修饰的属性

(1)解析AbstractBeanFactory类的doGetBean(String name, Class requiredType, Object[] args, boolean typeCheckOnly)方法

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
    throws BeansException {
    /***********省略其他代码***********/
    if (mbd.isSingleton()) {
        sharedInstance = getSingleton(beanName, () -> {
            try {
                return createBean(beanName, mbd, args);
            } catch (BeansException ex) {
                destroySingleton(beanName);
                throw ex;
            }
        });
        beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }
    /***********省略其他代码***********/
    return adaptBeanInstance(name, beanInstance, requiredType);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在AbstractBeanFactory类的doGetBean()方法中,如果是单例Bean,会调用getSingleton()方法创建单例Bean,实际执行的是Lambda表达式中的createBean()方法来创建单例Bean。

(2)解析AbstractAutowireCapableBeanFactory类的createBean(String beanName, RootBeanDefinition mbd, Object[] args)。

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    throws BeanCreationException {	
    /**************省略其他代码***************/
    try {
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
            mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

在AbstractAutowireCapableBeanFactory类的createBean()方法中,会调用doCreateBean()方法创建Bean对象。

(3)解析AbstractAutowireCapableBeanFactory类的doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)方法

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    throws BeanCreationException {
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    /***********省略其他代码**********/
    return exposedObject;
}
1
2
3
4
5
6
7
8
9
10
11
12

(4)解析AbstractAutowireCapableBeanFactory类的(String beanName, RootBeanDefinition mbd, Object[] args)方法

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // Make sure bean class is actually resolved at this point.
    Class<?> beanClass = resolveBeanClass(mbd, beanName);
    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    }
    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    if (instanceSupplier != null) {
        return obtainFromSupplier(instanceSupplier, beanName);
    }
    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
        synchronized (mbd.constructorArgumentLock) {
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                resolved = true;
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }
    if (resolved) {
        if (autowireNecessary) {
            return autowireConstructor(beanName, mbd, null, null);
        }
        else {
            return instantiateBean(beanName, mbd);
        }
    }
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
        mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        return autowireConstructor(beanName, mbd, ctors, args);
    }
    ctors = mbd.getPreferredConstructors();
    if (ctors != null) {
        return autowireConstructor(beanName, mbd, ctors, null);
    }
    return instantiateBean(beanName, mbd);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

createBeanInstance()方法会创建Bean的实例并返回BeanWrapper对象。

(5)返回AbstractAutowireCapableBeanFactory类的doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)方法,此时,重点关注如下代码片段。

/*************省略其他代码***************/
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex);
            }
            mbd.markAsPostProcessed();
        }
    }
    /*************省略其他代码***************/
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在AbstractAutowireCapableBeanFactory类的doCreateBean()方法中会调用applyMergedBeanDefinitionPostProcessors()方法的主要作用就是:获取@Value、@Autowired、@PostConstruct、@PreDestroy等注解标注的字段和方法,然后封装到InjectionMetadata对象中,最后将所有的InjectionMetadata对象存入injectionMeatadataCache缓存中。

(6)解析AbstractAutowireCapableBeanFactory类的applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName)方法

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
    for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
        processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
    }
}
1
2
3
4
5

在AbstractAutowireCapableBeanFactory类的applyMergedBeanDefinitionPostProcessors()方法中,会调用processor的postProcessMergedBeanDefinition()方法处理BeanDefinition信息。

(7)解析AutowiredAnnotationBeanPostProcessor类postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)。

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    findInjectionMetadata(beanName, beanType, beanDefinition);
}
1
2
3
4

在AutowiredAnnotationBeanPostProcessor类postProcessMergedBeanDefinition()方法中会调用findInjectionMetadata()方法来获取标注了注解的字段或者方法。

(8)解析AutowiredAnnotationBeanPostProcessor类的findInjectionMetadata(String beanName, Class<?> beanType, RootBeanDefinition beanDefinition)方法

private InjectionMetadata findInjectionMetadata(String beanName, Class<?> beanType, RootBeanDefinition beanDefinition) {
    InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
    return metadata;
}
1
2
3
4
5

在AutowiredAnnotationBeanPostProcessor类的findInjectionMetadata()方法中,调用了findAutowiringMetadata方法来解析并获取@Value、@Autowired、@Inject等注解修饰的属性或者方法。

(9)解析AutowiredAnnotationBeanPostProcessor类的findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs)方法

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        synchronized (this.injectionMetadataCache) {
            metadata = this.injectionMetadataCache.get(cacheKey);
            if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                if (metadata != null) {
                    metadata.clear(pvs);
                }
                metadata = buildAutowiringMetadata(clazz);
                this.injectionMetadataCache.put(cacheKey, metadata);
            }
        }
    }
    return metadata;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

AutowiredAnnotationBeanPostProcessor类的findAutowiringMetadata()方法最核心的功能就是对传递进来的每个类进行筛选判断是否被@Value、@Autowired、@Inject注解修饰的方法或者属性,如果是被 @Value、@Autowired、@Inject注解修饰的方法或者属性,就会将这个类记录下来,存入injectionMetadataCache缓存中,为后续的 DI 依赖注作准备。

首次调用findAutowiringMetadata()方法时,会调用buildAutowiringMetadata()方法来查找使用@Value、@Autowired、@Inject注解修饰的方法或者属性。

(10)解析AutowiredAnnotationBeanPostProcessor类的buildAutowiringMetadata(Class<?> clazz)方法。

private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
    if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
        return InjectionMetadata.EMPTY;
    }
    List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    Class<?> targetClass = clazz;
    do {
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
        ReflectionUtils.doWithLocalFields(targetClass, field -> {
            MergedAnnotation<?> ann = findAutowiredAnnotation(field);
            if (ann != null) {
                if (Modifier.isStatic(field.getModifiers())) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation is not supported on static fields: " + field);
                    }
                    return;
                }
                boolean required = determineRequiredStatus(ann);
                currElements.add(new AutowiredFieldElement(field, required));
            }
        });
        /**************省略其他代码****************/
        elements.addAll(0, currElements);
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);
    return InjectionMetadata.forElements(elements, clazz);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

在AutowiredAnnotationBeanPostProcessor类的buildAutowiringMetadata()方法中,获取到类上所有的字段,然后遍历每个字段,判断是否标注了 @Value、@Autowired和@Inject注解,如果标注了 @Value、@Autowired和@Inject注解,直接封装成 AutowiredFieldElement 对象,然后保存到一个名为 currElements集合中。

如果解析到的字段是静态字段,则直接返回,这就是为什么Spring不会对类中的静态字段赋值的原因。如下代码片段所示。

if (Modifier.isStatic(field.getModifiers())) {
    if (logger.isInfoEnabled()) {

        logger.info("Autowired annotation is not supported on static fields: " + field);

    }

    return;
}
1
2
3
4
5
6
7
8
9

在AutowiredAnnotationBeanPostProcessor类的buildAutowiringMetadata()方法的最后,则将标注了@Value、@Autowired和@Inject注解的字段封装到 InjectionMetadata 对象中,如下所示。

return InjectionMetadata.forElements(elements, clazz);
1

最终回到AutowiredAnnotationBeanPostProcessor类的findAutowiringMetadata()方法中,将InjectionMetadata 对象存入injectionMetadataCache缓存中。

metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
1
2

另外,在AutowiredAnnotationBeanPostProcessor类的buildAutowiringMetadata()方法中,调用了findAutowiredAnnotation()方法来获取注解信息。

MergedAnnotation<?> ann = findAutowiredAnnotation(field);
1

(11)解析AutowiredAnnotationBeanPostProcessor类的findAutowiredAnnotation(AccessibleObject ao)方法

private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
    MergedAnnotations annotations = MergedAnnotations.from(ao);
    for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
        MergedAnnotation<?> annotation = annotations.get(type);
        if (annotation.isPresent()) {
            return annotation;
        }
    }
    return null;
}
1
2
3
4
5
6
7
8
9
10

在AutowiredAnnotationBeanPostProcessor类的findAutowiredAnnotation()方法中,会遍历autowiredAnnotationTypes集合,通过遍历出的每个autowiredAnnotationTypes集合中的元素从annotations中获取MergedAnnotation对象annotation,如果annotation存在,则返回annotation。否则返回null。

需要关注下autowiredAnnotationTypes集合,在AutowiredAnnotationBeanPostProcessor类的构造方法中向autowiredAnnotationTypes集合中添加元素。

public AutowiredAnnotationBeanPostProcessor() {
    this.autowiredAnnotationTypes.add(Autowired.class);
    this.autowiredAnnotationTypes.add(Value.class);
    try {
        this.autowiredAnnotationTypes.add((Class<? extends Annotation>) ClassUtils.forName("jakarta.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
        logger.trace("'jakarta.inject.Inject' annotation found and supported for autowiring");
    }
    catch (ClassNotFoundException ex) {
        // jakarta.inject API not available - simply skip.
    }
    try {
        this.autowiredAnnotationTypes.add((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
        logger.trace("'javax.inject.Inject' annotation found and supported for autowiring");
    }
    catch (ClassNotFoundException ex) {
        // javax.inject API not available - simply skip.
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

在AutowiredAnnotationBeanPostProcessor类的构造方法中,向autowiredAnnotationTypes集合中添加了@Autowired注解、@Value注解和@Inject注解。所以,@Autowired注解赋值的流程和@Value注解赋值的流程基本一致。

# 为@Value修饰的属性赋值

(1)解析AbstractAutowireCapableBeanFactory类的doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)方法

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
    /************省略其他代码*************/
    Object exposedObject = bean;
    try {
        populateBean(beanName, mbd, instanceWrapper);
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException bce && beanName.equals(bce.getBeanName())) {
            throw bce;
        }
        else {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex);
        }
    }
    /************省略其他代码*************/
    return exposedObject;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

在AbstractAutowireCapableBeanFactory类的doCreateBean()方法中,会调用populateBean方法为Bean的属性赋值。

(2)解析AbstractAutowireCapableBeanFactory类的populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)方法

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    /**************省略其他代码*************/
    if (hasInstantiationAwareBeanPostProcessors()) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                return;
            }
            pvs = pvsToUse;
        }
    }
    /**************省略其他代码*************/
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

在populateBean()方法中,会调用InstantiationAwareBeanPostProcessor类的postProcessProperties()方法来处理属性或方法的值。实际上是调用的AutowiredAnnotationBeanPostProcessor类的postProcessProperties()方法。

(3)解析AutowiredAnnotationBeanPostProcessor类的postProcessProperties(PropertyValues pvs, Object bean, String beanName)方法

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
        metadata.inject(bean, beanName, pvs);
    }
    catch (BeanCreationException ex) {
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    }
    return pvs;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

在AutowiredAnnotationBeanPostProcessor类的postProcessProperties()方法中,会调用findAutowiringMetadata()方法获取注解的元数据信息。

(4)解析AutowiredAnnotationBeanPostProcessor类的findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs)方法

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        synchronized (this.injectionMetadataCache) {
            metadata = this.injectionMetadataCache.get(cacheKey);
            if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                if (metadata != null) {
                    metadata.clear(pvs);
                }
                metadata = buildAutowiringMetadata(clazz);
                this.injectionMetadataCache.put(cacheKey, metadata);
            }
        }
    }
    return metadata;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

由于在之前解析并获取@Value修饰的属性的代码流程中,已经完成了对@Value 修饰的属性的获取工作。所以,程序执行到findAutowiringMetadata()方法内部时,injectionMetadataCache缓存中已经有数据了。

(5)返回AutowiredAnnotationBeanPostProcessor类的postProcessProperties(PropertyValues pvs, Object bean, String beanName)方法。在AutowiredAnnotationBeanPostProcessor类的postProcessProperties()方法中,调用了metadata对象的inject()方法为属性赋值。

(6)解析InjectionMetadata类的inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs)方法

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Collection<InjectedElement> checkedElements = this.checkedElements;
    Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements);
    if (!elementsToIterate.isEmpty()) {
        for (InjectedElement element : elementsToIterate) {
            element.inject(target, beanName, pvs);
        }
    }
}
1
2
3
4
5
6
7
8
9

在InjectionMetadata类的inject()方法中,会循环遍历checkedElements集合,调用遍历出的每个InjectedElement对象的inject()方法为属性赋值。

注意:调用InjectedElement对象的inject()方法时,实际上可能会调用AutowiredFieldElement类的inject()方法、AutowiredMethodElement类的inject()方法或者InjectedElement类的inject()方法。这里,以调用AutowiredFieldElement类的inject()方法为例进行说明。

(7)解析AutowiredFieldElement类的inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs)方法

@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Field field = (Field) this.member;
    Object value;
    if (this.cached) {
        try {
            value = resolvedCachedArgument(beanName, this.cachedFieldValue);
        }
        catch (NoSuchBeanDefinitionException ex) {
            value = resolveFieldValue(field, bean, beanName);
        }
    }
    else {
        value = resolveFieldValue(field, bean, beanName);
    }
    if (value != null) {
        ReflectionUtils.makeAccessible(field);
        field.set(bean, value);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

在AutowiredFieldElement类的inject()方法中,会调用resolveFieldValue()方法来获取对应的属性值,如下所示。

value = resolveFieldValue(field, bean, beanName);
1

并通过反射向使用@Value注解标注的字段赋值,如下所示。

 field.set(bean, value);
1

(8)返回AbstractAutowireCapableBeanFactory类的doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)方法。再来看下源码:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
   throws BeanCreationException {
    /************省略其他代码*************/
   Object exposedObject = bean;
   try {
     populateBean(beanName, mbd, instanceWrapper);
     exposedObject = initializeBean(beanName, exposedObject, mbd);
   }
   catch (Throwable ex) {
     if (ex instanceof BeanCreationException bce && beanName.equals(bce.getBeanName())) {
       throw bce;
     }
     else {
       throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex);
     }
   }
    /************省略其他代码*************/
   return exposedObject;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

在AbstractAutowireCapableBeanFactory类的doCreateBean()方法中,为Bean的属性赋值后会调用initializeBean()方法对Bean进行初始化。

(9)解析AbstractAutowireCapableBeanFactory类的initializeBean(String beanName, Object bean, RootBeanDefinition mbd)方法

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
   invokeAwareMethods(beanName, bean);
   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) {
     wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }
   try {
     invokeInitMethods(beanName, wrappedBean, mbd);
   }
   catch (Throwable ex) {
     throw new BeanCreationException(   
       (mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex);
   }
   if (mbd == null || !mbd.isSynthetic()) {
     wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }
   return wrappedBean;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

在AbstractAutowireCapableBeanFactory类的initializeBean()方法中,会调用applyBeanPostProcessorsBeforeInitialization()方法在初始化之前执行一些逻辑,然后调用invokeInitMethods()执行真正的初始化操作,执行完Bean的初始化,会调用applyBeanPostProcessorsAfterInitialization()方法执行初始化之后的一些逻辑。

# 使用@Value获取属性的值

(1)解析AutowiredFieldElement类的inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs)方法

@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Field field = (Field) this.member;
    Object value;
    if (this.cached) {
        try {
            value = resolvedCachedArgument(beanName, this.cachedFieldValue);
        }
        catch (NoSuchBeanDefinitionException ex) {
            // Unexpected removal of target bean for cached argument -> re-resolve
            value = resolveFieldValue(field, bean, beanName);
        }
    } 
    else {
        value = resolveFieldValue(field, bean, beanName);
    } 
    if (value != null) { 
        ReflectionUtils.makeAccessible(field);
        field.set(bean, value);  
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

在AutowiredFieldElement类的inject()方法中,会调用resolveFieldValue()方法处理获取属性的值。

(2)解析AutowiredFieldElement类的resolveFieldValue(Field field, Object bean, @Nullable String beanName)方法

@Nullable
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
    /*************省略其他代码************/
    Object value;
    try {
        value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    }
    catch (BeansException ex) {
        throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
    } 
     /*************省略其他代码************/
 return value;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

在AutowiredFieldElement类的resolveFieldValue()方法中,会调用beanFactory对象的resolveDependency()方法

(3)解析DefaultListableBeanFactory类的resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter)

@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

    /***************省略其他代码**************/
    
    else {
        Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);    
        if (result == null) {  
            result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); 
        }  
        return result;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

在DefaultListableBeanFactory类的resolveDependency()方法中,会调用doResolveDependency()方法进一步处理。

(4)解析DefaultListableBeanFactory类的doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter)方法

@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
	/************省略其他代码*************/
	Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);	
	if (value != null) {
	    if (value instanceof String strValue) {
	        String resolvedValue = resolveEmbeddedValue(strValue);
	        BeanDefinition bd = (beanName != null && containsBean(beanName) ?
	                             getMergedBeanDefinition(beanName) : null);
	        value = evaluateBeanDefinitionString(resolvedValue, bd);
	    }
	    TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
	    try {
	        return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
	    }
	    catch (UnsupportedOperationException ex) {
	        // A custom TypeConverter which does not support TypeDescriptor resolution...	
	        return (descriptor.getField() != null ?	
	                converter.convertIfNecessary(value, type, descriptor.getField()) :	
	                converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));	
	    }	
	}	
	/************省略其他代码*************/
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

在DefaultListableBeanFactory类的doResolveDependency()方法中,如果当前获取到的数据是String类型,则调用resolveEmbeddedValue()方法进行处理。

(5)解析AbstractBeanFactory类的resolveEmbeddedValue(@Nullable String value)方法

@Override
@Nullable
public String resolveEmbeddedValue(@Nullable String value) {
    if (value == null) {  
        return null; 
    }  
    String result = value;  
    for (StringValueResolver resolver : this.embeddedValueResolvers) {   
        result = resolver.resolveStringValue(result); 
        if (result == null) {   
            return null;  
        }  
    }  
    return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在AbstractBeanFactory类的resolveEmbeddedValue()中,会调用遍历出来的StringValueResolver对象的resolveStringValue()方法进行处理。此时,会进入AbstractEnvironment类的resolvePlaceholders(String text)方法。

(6)解析AbstractEnvironment类的resolvePlaceholders(String text)方法

@Override
public String resolvePlaceholders(String text) {
    return this.propertyResolver.resolvePlaceholders(text);
}
1
2
3
4

在AbstractEnvironment类的resolvePlaceholders()方法中,会调用propertyResolver对象的resolvePlaceholders()方法进行处理。

(7)解析AbstractPropertyResolver类的resolvePlaceholders(String text)方法

@Override
public String resolvePlaceholders(String text) {
    if (this.nonStrictHelper == null) {
        this.nonStrictHelper = createPlaceholderHelper(true);  
    }  
    return doResolvePlaceholders(text, this.nonStrictHelper);
}
1
2
3
4
5
6
7

在AbstractPropertyResolver类的resolvePlaceholders()方法中,会调用doResolvePlaceholders()方法进一步处理。

(8)解析AbstractPropertyResolver类的doResolvePlaceholders(String text, PropertyPlaceholderHelper helper)方法

private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
    return helper.replacePlaceholders(text, this::getPropertyAsRawString);
}
1
2
3

在AbstractPropertyResolver类的doResolvePlaceholders()方法中,会解析 ${xxx.xxx (opens new window)} 这种占位,最终获取到 key = xxx.xxx (opens new window),随后根据key去资源文件(xml、application.properties、Environment 等)中查找是否配置了这个key的值。其实是通过调用helper的replacePlaceholders()方法并以Lambda表达式的方式传入getPropertyAsRawString()方法实现的。

(9)解析PropertyPlaceholderHelper类的replacePlaceholders(String value, PlaceholderResolver placeholderResolver)方法

public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) {
    Assert.notNull(value, "'value' must not be null");   
    return parseStringValue(value, placeholderResolver, null);
}
1
2
3
4

在PropertyPlaceholderHelper类的replacePlaceholders()方法中,会调用parseStringValue()方法解析String类型的数据。

(10)解析PropertyPlaceholderHelper类的parseStringValue(String value, PlaceholderResolver placeholderResolver, @Nullable Set visitedPlaceholders)方法

protected String parseStringValue(String value, PlaceholderResolver placeholderResolver, @Nullable Set<String> visitedPlaceholders) {
    /***************省略其他代码****************/ 
    // Now obtain the value for the fully resolved key...    
    String propVal = placeholderResolver.resolvePlaceholder(placeholder);   
    if (propVal == null && this.valueSeparator != null) {  
        int separatorIndex = placeholder.indexOf(this.valueSeparator);   
        if (separatorIndex != -1) {  
            String actualPlaceholder = placeholder.substring(0, separatorIndex); 
            String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length()); 
            propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);  
            if (propVal == null) {
                propVal = defaultValue; 
            } 
        }   
    }  
    /**********省略其他代码***********/
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

重点关注如下代码片段。

String propVal = placeholderResolver.resolvePlaceholder(placeholder);
1

会调用placeholderResolver对象的resolvePlaceholder()方法传入解析 ${xxx.xxx (opens new window)} 占位符,获取到的key,其中key的形式为xxx.xxx (opens new window)。调用placeholderResolver对象的resolvePlaceholder()方法会最终调用PropertySourcesPropertyResolver类的getPropertyAsRawString()方法。

(11)解析PropertySourcesPropertyResolver类的getPropertyAsRawString(String key)方法

@Override
@Nullable
protected String getPropertyAsRawString(String key) {
    return getProperty(key, String.class, false);
}
1
2
3
4
5

在getPropertyAsRawString()方法中,会调用getProperty()方法获取属性的值。在调用getPropertyAsRawString()方法时,传入的Key的形式的规则就是:如果使用@Value标注的属性为 ${xxx.xxx (opens new window)} 占位符,则此处传入的Key的形式为xxx.xxx (opens new window)。

(12)解析PropertySourcesPropertyResolver类的getProperty(String key, Class targetValueType, boolean resolveNestedPlaceholders)方法

@Nullable
protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {
    if (this.propertySources != null) {  
        for (PropertySource<?> propertySource : this.propertySources) {  
            if (logger.isTraceEnabled()) {   
                logger.trace("Searching for key '" + key + "' in PropertySource '" +  
                             propertySource.getName() + "'");   
            }   
            Object value = propertySource.getProperty(key);  
            if (value != null) {
              if (resolveNestedPlaceholders && value instanceof String string) {
                    value = resolveNestedPlaceholders(string);  
                }
              logKeyFound(key, propertySource, value);  
                return convertValueIfNecessary(value, targetValueType);   
            } 
        }    
    }   
    if (logger.isTraceEnabled()) {  
        logger.trace("Could not find key '" + key + "' in any property source");   
    }    
    return null;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

在PropertySourcesPropertyResolver类的getProperty()方法中,会从 propertySources 资源中获取 key = xxx.xxx (opens new window) 的值,如果获取到一个对应的值,就会直接返回。其中,在propertySources中会封装PropertiesPropertySource、SystemEnvironmentPropertySource和ResourcePropertySource类型的对象。每种类型的对象中封装的信息如下所示。

  1. PropertiesPropertySource:封装 JVM 环境变量中的键值对。
  2. SystemEnvironmentPropertySource:封装操作系统环境变量中的键值对。
  3. ResourcePropertySource:封装项目中application.properties、yml和xml等文件中的键值对。

从ResourcePropertySource对象中获取到对应的值就可以设置到被@Value注解标注的字段上。

# 思考

# 1. @Value注解的作用

@Value注解用于将配置信息或特定的值注入到Bean的字段、方法参数或返回值中。它可以将外部配置(如application.properties或application.yml文件中的属性)或字面量值(如字符串、数字等)注入到Bean中,从而避免了硬编码,提高了代码的可维护性和灵活性。

# 2. @Value注解的使用场景

  1. 注入外部配置:将application.properties或application.yml等配置文件中的属性值注入到Bean的字段中,以便在应用程序中使用这些配置。
  2. 注入字面量值:直接注入简单的字面量值,如字符串、数字等,到Bean的字段中。
  3. 注入系统属性:通过SpEL(Spring Expression Language)表达式注入系统属性,如@Value("#{systemProperties['java.home']}")。
  4. 注入表达式结果:使用SpEL表达式计算结果并注入到Bean的字段中,如@Value("#{ T(java.lang.Math).random() * 100.0 }")。
  5. 注入其他Bean的属性:通过SpEL表达式注入其他Bean的属性值,如@Value("#{otherBean.propertyName}")。

# 3. @Value向Bean的字段和方法注入值是如何实现的

@Value向Bean的字段和方法注入值主要通过Spring的依赖注入(DI)机制实现。具体来说,当Spring容器启动时,它会扫描带有@Component、@Service等注解的类,并识别出这些类中的@Value注解。对于字段上的@Value注解,Spring会在Bean实例化后,通过反射机制将配置值或字面量值注入到相应的字段中。对于方法参数上的@Value注解,通常用于构造器注入或Setter方法注入,Spring会在调用构造器或Setter方法时,将值作为参数传递给这些方法。

# 4. @Value注解在Spring内部的执行流程

@Value注解在Spring内部的执行流程大致如下:

  1. 扫描与解析:Spring容器在启动时,会扫描带有@Component等注解的类,并解析这些类中的@Value注解。
  2. 值解析:对于@Value注解中的值,Spring会进行解析。如果值是简单的字面量,则直接解析为相应的类型;如果值是占位符(如${key}),则会从配置文件中查找对应的值;如果值是SpEL表达式,则会计算表达式的结果。
  3. 依赖注入:将解析后的值注入到Bean的字段中或通过方法参数传递给Bean的构造器或Setter方法。

# 5. @Value注解在Spring源码中的执行流程与@Autowired注解的区别

  1. 用途区别:
    • @Value注解主要用于注入配置信息或字面量值,它更侧重于将外部配置或静态值注入到Bean中。
    • @Autowired注解则主要用于自动装配Bean,它可以根据类型或名称自动将Bean注入到其他Bean的字段、构造器或Setter方法中,实现Bean之间的依赖关系。
  2. 注入方式区别:
    • @Value注解的注入方式比较灵活,可以注入简单的字面量值、配置文件中的值、系统属性、表达式结果等。
    • @Autowired注解的注入方式相对固定,它主要根据类型或名称进行注入,且主要用于Bean之间的依赖注入。
  3. 执行流程区别:
    • 在执行流程上,@Value注解和@Autowired注解都会经历扫描、解析和依赖注入等阶段,但具体的解析逻辑和注入方式有所不同。@Value注解需要解析占位符和SpEL表达式,而@Autowired注解则需要根据类型或名称查找并注入Bean。

# 1.12 @Autowired注解

@Autowired注解能够自动按照类型注入。当IOC容器中有且仅有一个类型匹配时,使用@Autowired注解可以直接注入成功。当超过一个类型匹配时,则使用变量名称(写在方法上就是方法名称)作为Bean的id,在符合类型的多个Bean中再次进行匹配,如果能匹配上就可以注入成功。如果匹配不上,是否报错要看required属性的取值。

# 注解源码

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
	boolean required() default true;
}
1
2
3
4
5
6
  • required:表示是否必须注入成功,取值为true或false。默认值是true,表示必须注入成功。当取值为true时,注入不成功会报错,否则,注入不成功不会报错。

# 源码时序图

1.12.1

1.12.2

# 源码解析

解析并获取 @Autowired修饰的属性、为 @Autowired修饰属性赋值的源码流程基本与@Value相同,只是使用@Autowired获取属性值的源码流程略有差异。使用@Autowired获取属性值的源码流程如下:

(1)直接来到AutowiredAnnotationBeanPostProcessor类的inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs)方法。

@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
   Field field = (Field) this.member;
   Object value;
   if (this.cached) {
     try {   
       value = resolvedCachedArgument(beanName, this.cachedFieldValue);  
     } 
     catch (NoSuchBeanDefinitionException ex) {
       // Unexpected removal of target bean for cached argument -> re-resolve
       value = resolveFieldValue(field, bean, beanName); 
     }
   }
   else {
     value = resolveFieldValue(field, bean, beanName);
   }
   if (value != null) {
     ReflectionUtils.makeAccessible(field);
     field.set(bean, value);
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

在AutowiredAnnotationBeanPostProcessor类的inject()方法中,会调用resolveFieldValue()方法处理字段的值。

(2)解析AutowiredFieldElement类的resolveFieldValue(Field field, Object bean, @Nullable String beanName)方法

@Nullable
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
   DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
   desc.setContainingClass(bean.getClass());
   Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
   Assert.state(beanFactory != null, "No BeanFactory available");
   TypeConverter typeConverter = beanFactory.getTypeConverter();
   Object value;
   try {
     value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
   }
   catch (BeansException ex) {
     throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
   }
   /************省略其他代码*************/
   return value;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在resolveFieldValue()方法中,会调用beanFactory对象的resolveDependency()方法处理Bean的依赖。

(3)解析DefaultListableBeanFactory类的resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter)方法

@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    /**********省略其他代码***********/
    else {
        Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
            descriptor, requestingBeanName);
        if (result == null) {
            result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
        }
        return result;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

在DefaultListableBeanFactory类的resolveDependency()方法中,调用了doResolveDependency()方法来处理Bean的依赖。

(4)解析DefaultListableBeanFactory类的doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter)方法

@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,  @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    try { 
        Object shortcut = descriptor.resolveShortcut(this); 
        if (shortcut != null) {  
            return shortcut; 
        }
        Class<?> type = descriptor.getDependencyType();
        Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); 
        if (value != null) {
            if (value instanceof String strValue) {
                String resolvedValue = resolveEmbeddedValue(strValue);
                BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
                value = evaluateBeanDefinitionString(resolvedValue, bd);
            }
            TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
            try {
                return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
            }
            catch (UnsupportedOperationException ex) {
                // A custom TypeConverter which does not support TypeDescriptor resolution...
                return (descriptor.getField() != null ?
                        converter.convertIfNecessary(value, type, descriptor.getField()) :
                        converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
            }
        }  
        Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
        if (multipleBeans != null) {
            return multipleBeans;
        }
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        if (matchingBeans.isEmpty()) {
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            return null;
        }
    	/************省略其他代码**************/
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

在DefaultListableBeanFactory类的doResolveDependency()方法中,调用了findAutowireCandidates()方法来查找符合条件的被@Autowired注解注入的Bean。

(5)解析DefaultListableBeanFactory类的findAutowireCandidates(@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor)方法

protected Map<String, Object> findAutowireCandidates(@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
    /***********省略其他代码***********/
    for (String candidate : candidateNames) {
        if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
            addCandidateEntry(result, candidate, descriptor, requiredType);
        }
    }
    if (result.isEmpty()) {
        boolean multiple = indicatesMultipleBeans(requiredType);
        DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
        for (String candidate : candidateNames) {
            if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) && (!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
                addCandidateEntry(result, candidate, descriptor, requiredType);
            }
        }
        if (result.isEmpty() && !multiple) {
            for (String candidate : candidateNames) {
                if (isSelfReference(beanName, candidate) &&
                    (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
                    isAutowireCandidate(candidate, fallbackDescriptor)) {
                    addCandidateEntry(result, candidate, descriptor, requiredType);
                }
            }
        }
    } 
    return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

在DefaultListableBeanFactory类的findAutowireCandidates()的方法中,会调用isAutowireCandidate()方法判断是否要注入的Bean。

(6)解析DefaultListableBeanFactory类的isAutowireCandidate(String beanName, DependencyDescriptor descriptor)方法。

@Override
public boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor) throws NoSuchBeanDefinitionException {
    return isAutowireCandidate(beanName, descriptor, getAutowireCandidateResolver());
}
1
2
3
4

在DefaultListableBeanFactory类的isAutowireCandidate()方法中调用了一个重载的isAutowireCandidate()方法。

(7)解析DefaultListableBeanFactory类的isAutowireCandidate(String beanName, DependencyDescriptor descriptor, AutowireCandidateResolver resolver)。

protected boolean isAutowireCandidate( String beanName, DependencyDescriptor descriptor, AutowireCandidateResolver resolver) throws NoSuchBeanDefinitionException {
    String bdName = BeanFactoryUtils.transformedBeanName(beanName);
    if (containsBeanDefinition(bdName)) {
        return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(bdName), descriptor, resolver); 
    }
    else if (containsSingleton(beanName)) {
        return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor, resolver);
    }
    /**********省略其他代码***********/
}


1
2
3
4
5
6
7
8
9
10
11
12

在重载的isAutowireCandidate()方法中,还会调用另一个重载的isAutowireCandidate()方法。

(9)解析DefaultListableBeanFactory类的isAutowireCandidate(String beanName, RootBeanDefinition mbd, DependencyDescriptor descriptor, AutowireCandidateResolver resolver)方法

protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd, DependencyDescriptor descriptor, AutowireCandidateResolver resolver) {

    /***********省略其他代码************/
    
    return resolver.isAutowireCandidate(holder, descriptor);

}
1
2
3
4
5
6
7

在DefaultListableBeanFactory类的isAutowireCandidate()方法中,会调用resolver对象的isAutowireCandidate()方法。

(10)解析QualifierAnnotationAutowireCandidateResolver类的isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor)方法

@Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
    boolean match = super.isAutowireCandidate(bdHolder, descriptor);
    if (match) {
        match = checkQualifiers(bdHolder, descriptor.getAnnotations());
        if (match) {
            MethodParameter methodParam = descriptor.getMethodParameter();
            if (methodParam != null) {
                Method method = methodParam.getMethod();
                if (method == null || void.class == method.getReturnType()) {
                    match = checkQualifiers(bdHolder, methodParam.getMethodAnnotations());
                }
            }
        }
    }   
    return match;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在QualifierAnnotationAutowireCandidateResolver类的isAutowireCandidate()方法中,会调用checkQualifiers()方法来检验是否标注了@Qualifier注解,并注入@Qualifier注解指定的Bean。

(11)QualifierAnnotationAutowireCandidateResolver类的checkQualifiers(BeanDefinitionHolder bdHolder, Annotation[] annotationsToSearch)方法

protected boolean checkQualifiers(BeanDefinitionHolder bdHolder, Annotation[] annotationsToSearch) {
    if (ObjectUtils.isEmpty(annotationsToSearch)) {
        return true;
    }
    SimpleTypeConverter typeConverter = new SimpleTypeConverter();
    for (Annotation annotation : annotationsToSearch) {
        Class<? extends Annotation> type = annotation.annotationType();
        boolean checkMeta = true;
        boolean fallbackToMeta = false;
        if (isQualifier(type)) { 
            if (!checkQualifier(bdHolder, annotation, typeConverter)) {
                fallbackToMeta = true;
            }
            else {
                checkMeta = false;
            }
        }
        if (checkMeta) {
            boolean foundMeta = false;
            for (Annotation metaAnn : type.getAnnotations()) {
                Class<? extends Annotation> metaType = metaAnn.annotationType();
                if (isQualifier(metaType)) {
                    foundMeta = true;
                    if ((fallbackToMeta && ObjectUtils.isEmpty(AnnotationUtils.getValue(metaAnn))) ||
                        !checkQualifier(bdHolder, metaAnn, typeConverter)) {
                        return false;
                    }
                }
            }
            if (fallbackToMeta && !foundMeta) {  
                return false;
            } 
        }  
    }  
    return true;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

QualifierAnnotationAutowireCandidateResolver类的checkQualifiers()方法主要处理@Qualifier注解,向类的字段中注入@Qualifier注解指定的Bean。

(12)返回DefaultListableBeanFactory类的doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter)方法

关注如下代码片段。

@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,  @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    
    try {
        /*************省略*************/
        String autowiredBeanName;
        Object instanceCandidate;
    
        if (matchingBeans.size() > 1) {
            autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
            if (autowiredBeanName == null) {
                if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
                    return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
                }
                else {
                    return null;
                }
            }
            instanceCandidate = matchingBeans.get(autowiredBeanName);
        }
        else {
            // We have exactly one match.
            Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();

            autowiredBeanName = entry.getKey();
            instanceCandidate = entry.getValue();
        }
        if (autowiredBeanNames != null) {
            autowiredBeanNames.add(autowiredBeanName);
        }
        if (instanceCandidate instanceof Class) {
            instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
        }
        Object result = instanceCandidate;
        if (result instanceof NullBean) {
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            result = null;
        }
        if (!ClassUtils.isAssignableValue(type, result)) {
            throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
        }
        return result;
    }
    finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

DefaultListableBeanFactory类的doResolveDependency()方法中会根据findAutowireCandidates()方法的返回结果,解析出要向类的字段中注入的Bean对象并返回。

(13)返回AutowiredFieldElement类的resolveFieldValue(Field field, Object bean, @Nullable String beanName)方法

@Nullable
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {

   /**********省略其他代码************/
    synchronized (this) {
        if (!this.cached) {
            Object cachedFieldValue = null;
            if (value != null || this.required) {
                cachedFieldValue = desc;
                registerDependentBeans(beanName, autowiredBeanNames);
                if (autowiredBeanNames.size() == 1) {
                    String autowiredBeanName = autowiredBeanNames.iterator().next();
                    if (beanFactory.containsBean(autowiredBeanName) &&  beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                        cachedFieldValue = new ShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType());
                    }
                }
            }
            this.cachedFieldValue = cachedFieldValue;
            this.cached = true;
        }
    }
    return value;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

在AutowiredFieldElement类的resolveFieldValue()方法中,会将通过beanFactory对象的resolveDependency()方法解析出的Bean注入到IOC容器中,并返回解析的Bean。

(14)返回AutowiredAnnotationBeanPostProcessor类的inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs)方法。

@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    /*********省略其他代码***********/   
    if (value != null) {
        ReflectionUtils.makeAccessible(field);
        field.set(bean, value);
    }
}
1
2
3
4
5
6
7
8

在AutowiredAnnotationBeanPostProcessor类的inject()方法中,将获取到的依赖Bean会设置到对应的字段上。

# 思考

# 1. @Autowired注解的使用场景

  1. 字段注入:将Bean注入到类的字段中。这种方式简单直接,但可能导致类与Spring容器的耦合度增加,且无法通过构造函数明确依赖关系。
  2. 构造器注入:将Bean通过构造器参数注入。这种方式可以确保Bean在初始化时就完成了依赖的注入,有助于创建不可变对象,并且可以清晰地表达依赖关系。
  3. 方法注入:主要用于配置或初始化方法,Spring容器会在调用这些方法之前注入所需的Bean。这种方式比较少见,主要用于某些特殊的场景,如需要在Bean初始化后进行一些额外的设置。
  4. 集合注入:可以将多个Bean注入到集合类型的字段中,如List、Set等。这对于需要管理一组相似对象的场景非常有用。

# 2. @Autowired向Bean的字段和方法注入值的实现方式

  1. 字段注入:Spring容器在创建Bean实例后,通过反射机制找到被@Autowired注解的字段,然后查找匹配的Bean(如果有多个匹配的Bean,则根据类型或名称的匹配策略来决定),并将其注入到该字段中。
  2. 构造器注入:Spring容器会查看被@Autowired注解的构造器(如果有多个构造器,则按照特定规则选择),并查找构造器参数对应的Bean,然后创建Bean实例时注入这些依赖。
  3. 方法注入:类似于字段注入,但Spring容器会在Bean实例创建后(或在特定生命周期阶段),通过反射调用被@Autowired注解的方法,并将匹配的Bean作为参数传递给该方法。

# 3. @Autowired注解在Spring内部的执行流程

  1. Bean的创建:Spring容器在启动时或接收到Bean的请求时,会开始创建Bean的实例。
  2. 查找@Autowired注解:在Bean的创建过程中,Spring会检查Bean的类定义(包括字段、构造器、方法等),查找被@Autowired注解的元素。
  3. 依赖查找:对于每个被@Autowired注解的元素,Spring会查找匹配的Bean。这通常涉及到查找与注解元素类型兼容的Bean,并可能涉及名称的匹配(如果指定了@Qualifier注解)。
  4. 依赖注入:找到匹配的Bean后,Spring会通过反射机制将Bean注入到被@Autowired注解的元素中。这可能包括设置字段的值、调用构造器、或调用方法。
  5. 完成Bean的创建:一旦所有依赖都被注入,Bean的创建过程就完成了。Bean现在可以被使用或注入到其他Bean中。

# 1.13 @Qualifier注解

如果Spring中存在多个类型相同但名称不同的Bean时,使用@Autowired注解向类的构造方法、方法、参数、字段中注入Bean对象时,首先会根据Bean的类型注入,如果存在多个类型相同的Bean时,会根据Bean的名称注入,如果找不到对应名称的Bean时,就会抛出异常。此时,就可以通过@Qualifier注解明确指定要注入的Bean。

# 注解源码

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
	String value() default "";
}
1
2
3
4
5
6
7
  • value:表示Bean的唯一标识。当使用Spring自动按照类型注入时,存在多个类型相同的Bean的时候,就可以使用此注解来明确注入哪个bean对象。

# 源码解析

@Qualifier注解的源码时序图和源码解析与@Autowired基本相同,可参考@Autowired源码的解析流程

# 1.14 @Resource注解

@Resource注解是JSR250规范中提供的注解,主要作用就是通过JNDI技术查找依赖的组件并注入到类、字段和方法中来。默认情况下,不指定注解的任何属性时,会默认按照byName的方式装配Bean对象。如果指定了name属性,没有指定type属性,则采用byName的方式装配Bean对象。如果没有指定name属性,而是指定了type属性,则按照byType的方式装配bean对象。当同时指定了type属性和name属性,则两个属性都会校验,任何一个不符合条件就会报错。

当存在多个类型相同的Bean时,可以指定@Resource注解的name属性明确指定装配哪个Bean对象。相当于@Autowired注解与@Qualifier注解的组合。@Resource注解与@Qualifier注解也可以搭配使用,通过@Qualifier注解明确指定装配哪个Bean。

@Resource注解与@Autowired的主要区别如下所示。

(1)@Resource注解是JSR250规范中提供的注解,如果使用的JDK8版本,则无需额外导入依赖,如果使用的JDK版本低于8或者高于11,则需要额外导入依赖。@Autowired注解是Spring框架提供的注解。

(2)@Resource注解默认通过byName的方式装配Bean,找不到Bean的话,就通过byType的方式装配Bean。@Autowired注解默认根据byType的方式装配Bean,如果需要根据名称装配Bean,则需要结合@Qualifier注解一起使用。

(3)@Resource注解标注到类、字段和方法上。@Autowired注解标注到构造方法、方法、参数、字段、其他注解上。

# 注解源码

在Spring6中,使用@Resource注解需要额外在Maven中加入如下依赖。

<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>2.1.1</version>
</dependency>
1
2
3
4
5
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
@Repeatable(Resources.class)
public @interface Resource {
    String name() default "";
    String lookup() default "";
    Class<?> type() default java.lang.Object.class;
    enum AuthenticationType {
	    CONTAINER,
	    APPLICATION
    }
    AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
    boolean shareable() default true;
    String mappedName() default "";
    String description() default "";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  • name:资源的JNDI名称,装配指定名称的Bean。
  • type:装配指定类型的Bean。
  • lookup:引用指向的资源名称,可以使用JNDI名称指向任何兼容的资源。
  • AuthenticationType:指定身份验证类型。
  • shareable:指定当前Bean是否可以在多个组件之间共享。
  • mappedName:指定资源的映射名称。
  • description:指定资源的描述。

# 源码时序图

# 解析并获取@Resource修饰的属性

1.14.1

1.14.2

# 为@Resource修饰属性赋值

1.14.3

1.14.4

# 源码解析

# 解析并获取@Resource修饰的属性

解析并获取@Resource修饰的属性的源码流程总体上与解析并获取@Autowired修饰的属性的源码流程相同,所以这里只记录有差异的部分,从AbstractAutowireCapableBeanFactory类的applyMergedBeanDefinitionPostProcessors()方法开始解析。

(1)解析AbstractAutowireCapableBeanFactory类的applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName)方法

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
   for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
     processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
   }
}
1
2
3
4
5

在AbstractAutowireCapableBeanFactory类的applyMergedBeanDefinitionPostProcessors()方法中,会调用循环遍历出的processor对象的postProcessMergedBeanDefinition()方法。

(2)解析CommonAnnotationBeanPostProcessor类的postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)方法

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
   super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
   InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
   metadata.checkConfigMembers(beanDefinition);
}
1
2
3
4
5
6

在解析@Resource注解时,会进入CommonAnnotationBeanPostProcessor类的postProcessMergedBeanDefinition()。在CommonAnnotationBeanPostProcessor类的postProcessMergedBeanDefinition()方法中,调用了findResourceMetadata()方法来查找使用@Resource注解标注的资源,并返回了InjectionMetadata类的对象metadata。

(3)解析CommonAnnotationBeanPostProcessor类的findResourceMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs)方法

private InjectionMetadata findResourceMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
   // Fall back to class name as cache key, for backwards compatibility with custom callers.
   String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
   // Quick check on the concurrent map first, with minimal locking.
   InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
   if (InjectionMetadata.needsRefresh(metadata, clazz)) {
     synchronized (this.injectionMetadataCache) {
       metadata = this.injectionMetadataCache.get(cacheKey);
       if (InjectionMetadata.needsRefresh(metadata, clazz)) {
         if (metadata != null) {
           metadata.clear(pvs);
         }
         metadata = buildResourceMetadata(clazz);
         this.injectionMetadataCache.put(cacheKey, metadata);
       }
     }
   }
   return metadata;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

在CommonAnnotationBeanPostProcessor类的findResourceMetadata()方法中,首先会从injectionMetadataCache中获取InjectionMetadata对象,如果InjectionMetadata对象存在并且不需要刷新InjectionMetadata对象,则直接返回InjectionMetadata对象。否则,就调用buildResourceMetadata()方法来构建InjectionMetadata对象,并将其放入injectionMetadataCache缓存中。

(4)解析CommonAnnotationBeanPostProcessor类的buildResourceMetadata(Class<?> clazz)方法

private InjectionMetadata buildResourceMetadata(Class<?> clazz) {
   if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
     return InjectionMetadata.EMPTY;
   }

   List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
   Class<?> targetClass = clazz;
   do {
     final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();  
     ReflectionUtils.doWithLocalFields(targetClass, field -> { 
       if (ejbClass != null && field.isAnnotationPresent(ejbClass)) { 
         if (Modifier.isStatic(field.getModifiers())) {
           throw new IllegalStateException("@EJB annotation is not supported on static fields");
         } 
         currElements.add(new EjbRefElement(field, field, null)); 
       }
       else if (field.isAnnotationPresent(Resource.class)) {
         if (Modifier.isStatic(field.getModifiers())) {
           throw new IllegalStateException("@Resource annotation is not supported on static fields");
         }
         if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
           currElements.add(new ResourceElement(field, field, null));
         }  
       }  
     });
    
     /***********省略其他代码**********/
    
     elements.addAll(0, currElements);
     targetClass = targetClass.getSuperclass();
   }
   while (targetClass != null && targetClass != Object.class);
   return InjectionMetadata.forElements(elements, clazz);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

在CommonAnnotationBeanPostProcessor类的buildResourceMetadata()方法中,会获取类中声明的所有字段,并解析标注了@Resource注解的字段,并且当前字段如果是静态字段,就会抛出IllegalStateException异常。这也是@Resource注解不能为类的静态字段赋值的原因。最终,将解析出的字段封装成InjectionMetadata对象并返回,添加到injectionMetadataCache中,后续就可以直接从injectionMetadataCache中获取数据并处理。

# 为@Resource修饰属性赋值

由于为@Resource修饰属性赋值的源码流程总体上与为@Autowired修饰属性赋值的源码流程相同,直接从AbstractAutowireCapableBeanFactory类的populateBean()方法开始解析。

(1)解析AbstractAutowireCapableBeanFactory类的populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)方法

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
   /*************省略其他代码*************/
   if (hasInstantiationAwareBeanPostProcessors()) {
     if (pvs == null) {
       pvs = mbd.getPropertyValues();
     }

     for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {    
       PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
       if (pvsToUse == null) {
         return;
       }
       pvs = pvsToUse;
     }
   }
   /*************省略其他代码*************/
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在AbstractAutowireCapableBeanFactory类的populateBean()中,会调用遍历出的InstantiationAwareBeanPostProcessor对象的postProcessProperties()方法处理属性的值。

(2)解析CommonAnnotationBeanPostProcessor类的postProcessProperties(PropertyValues pvs, Object bean, String beanName)方法

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
   InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);

   try {
     metadata.inject(bean, beanName, pvs);
   }
   catch (Throwable ex) {
     throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
   }
   return pvs;
}
1
2
3
4
5
6
7
8
9
10
11
12

在解析@Resource注解时,会进入CommonAnnotationBeanPostProcessor类的postProcessProperties()方法。在postProcessProperties()方法中,会调用findResourceMetadata()方法查找被@Resource注解标注的资源。

(3)解析CommonAnnotationBeanPostProcessor类的findResourceMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs)方法

private InjectionMetadata findResourceMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {

   // Fall back to class name as cache key, for backwards compatibility with custom callers.
   String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());

   // Quick check on the concurrent map first, with minimal locking.
   InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);

   if (InjectionMetadata.needsRefresh(metadata, clazz)) {
     synchronized (this.injectionMetadataCache) {
       metadata = this.injectionMetadataCache.get(cacheKey);
       if (InjectionMetadata.needsRefresh(metadata, clazz)) {
         if (metadata != null) {
           metadata.clear(pvs);
         }
    
         metadata = buildResourceMetadata(clazz);
         this.injectionMetadataCache.put(cacheKey, metadata);
       } 
     }
   }
   return metadata;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

再次调用了findResourceMetadata()方法,由于在解析并获取@Resource修饰的属性时,就调用过findResourceMetadata()方法,并将获取到的InjectionMetadata对象存放到了injectionMetadataCache中,所以,后续会直接从injectionMetadataCache中获取数据并返回。

(4)返回CommonAnnotationBeanPostProcessor类的postProcessProperties(PropertyValues pvs, Object bean, String beanName)方法。

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
   InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
   try {
     metadata.inject(bean, beanName, pvs);
   }
   catch (Throwable ex) {
     throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
   }
   return pvs;
}
1
2
3
4
5
6
7
8
9
10
11

在postProcessProperties()方法中会调用InjectionMetadata对象metadata的inject()方法向字段中装配Bean。

(5)解析InjectionMetadata类的inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs)方法

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
   Collection<InjectedElement> checkedElements = this.checkedElements;
   Collection<InjectedElement> elementsToIterate =  (checkedElements != null ? checkedElements : this.injectedElements);
   if (!elementsToIterate.isEmpty()) {
     for (InjectedElement element : elementsToIterate) {  
       element.inject(target, beanName, pvs);  
     }
   }
}
1
2
3
4
5
6
7
8
9

在InjectionMetadata类的inject()方法中,会循环调用遍历出的InjectedElement对象的inject()方法,向类的字段中装配Bean。

(6)解析InjectedElement类的inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)方法

protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs) throws Throwable {
   if (this.isField) {
     Field field = (Field) this.member;    
     ReflectionUtils.makeAccessible(field);    
     field.set(target, getResourceToInject(target, requestingBeanName));
   }
  /**********省略其他代码************/
}
1
2
3
4
5
6
7
8

在InjectedElement类的inject()方法中,首先会通过getResourceToInject()方法来获取要注入的值,随后通过Java反射技术将值设置到对应的字段上。

(6)解析ResourceElement类的getResourceToInject(Object target, @Nullable String requestingBeanName)方法

@Override
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
   return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) : getResource(this, requestingBeanName));
}
1
2
3
4

在ResourceElement类的getResourceToInject()方法中,首先判断lazyLookup的值是否是true,如果为true,则调用buildLazyResourceProxy()方法返回结果,否则,调用getResource()方法返回结果。返回结果数据后,在在InjectedElement类的inject()方法中通过Java反射技术将返回的结果数据设置到对应的字段中。

# 思考

# 1. @Resource注解的使用场景

  1. 字段注入:直接在类的字段上使用@Resource注解,Spring会在创建Bean时自动注入该字段的值。
  2. 方法注入:在Setter方法或任意其他方法上使用@Resource,Spring会在Bean初始化时调用该方法,并将指定的Bean作为参数传入。
  3. 构造器注入:虽然@Resource本身不直接支持构造器注入的语法(如@Autowired的构造器注入),但可以通过指定name或type属性在构造器参数上实现类似效果(通常通过字段或Setter方法)。

# 2. @Resource向Bean的字段和方法注入值的实现

当Spring容器启动时,它会扫描所有Bean,寻找带有@Resource注解的字段、方法或构造函数参数。Spring通过以下几种方式之一来确定要注入的Bean:

  1. name属性:如果指定了name属性,Spring会尝试查找与该名称相匹配的Bean。
  2. type属性(较少使用):虽然@Resource支持type属性,但主要用于与EJB集成时指定接口类型。在Spring中,通常不需要指定type属性,因为Spring默认按类型查找。
  3. 默认行为:如果没有指定name或type,Spring首先按name查找(如果注解中隐含了名称,比如字段名),然后按类型查找。

一旦找到匹配的Bean,Spring会使用反射机制将其注入到被注解的字段或方法中。

# 3. @Resource与@Autowired的区别

  1. 来源:@Resource来自JSR-250规范,而@Autowired是Spring特有的注解。
  2. 依赖查找:@Autowired默认按类型查找,而@Resource可以通过name或type来指定查找方式。
  3. 必要性:@Autowired的required属性默认为true,表示依赖是必须的;而@Resource没有直接的required属性,但其行为可能受容器配置的影响。
  4. 异常处理:如果找不到匹配的Bean,@Autowired在required=true时会抛出异常,而@Resource在没有找到Bean时,行为可能因容器而异,但通常也会抛出异常或返回null(取决于容器的具体实现)。

# 1.15 @Scope注解

@Scope注解是Spring中提供的一个能够指定Bean的作用范围的注解,通过@Scope注解可以指定创建的Bean是单例的,还是原型的,也可以使用@Scope注解指定Bean在Web中的作用域,还可以自定义作用域。

# 注解源码

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {
	@AliasFor("scopeName")
	String value() default "";
	/**
	 * @since 4.2
	 */
	@AliasFor("value")
	String scopeName() default "";
	ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

@Scope注解中提供了三个属性含义分别如下:

  • value:表示作用范围,可以取如下值。
    • singleton:表示单例Bean,IOC容器在启动时,就会创建Bean对象。如果标注了@Lazy注解,IOC容器在启动时,就不会创建Bean对象,会在第一次从IOC容器中获取Bean对象时,创建Bean对象。后续每次从IOC容器中获取的都是同一个Bean对象,同时,IOC容器会接管单例Bean对象的生命周期。
    • prototype:表示原型Bean。IOC容器在启动时,不会创建Bean对象,每次从IOC容器中获取Bean对象时,都会创建一个新的Bean对象。并且@Lazy注解对原型Bean不起作用,同时,IOC容器不会接管原型Bean对象的生命周期
    • request:表示作用域是当前请求范围。
    • session:表示作用域是当前会话范围。
    • application:表示作用域是当前应用范围。
  • scopeName:Spring4.2版本开始新增的属性,作用与value属性相同。
  • proxyMode:指定Bean对象使用的代理方式,可以取如下值。
    • DEFAULT:默认值,作用与NO相同。
    • NO:不使用代理。
    • INTERFACES:使用JDK基于接口的代理。
    • TARGET_CLASS:使用CGLIB基于目标类的子类创建代理对象。

# 源码时序图

# 注册Bean的流程

1.15.1

# 调用Bean工厂后置处理器

1.15.2

1.15.3

# 获取Bean的流程

1.15.4

# 源码解析

# 注册Bean的流程

@Scope注解涉及到的注册Bean的源码流程与@DependsOn注解涉及到的注册Bean的源码流程大体相同,只是在解析AnnotatedBeanDefinitionReader类的doRegisterBean()方法时,略有不同。

(1)解析AnnotatedBeanDefinitionReader类的doRegisterBean(Class beanClass, String name, Class<? extends Annotation>[] qualifiers, Supplier supplier, BeanDefinitionCustomizer[] customizers)方法

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {

    /**************省略其他代码*****************/

   ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
   abd.setScope(scopeMetadata.getScopeName());
   String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

    /**************省略其他代码*****************/
   BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
   definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
   BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
1
2
3
4
5
6
7
8
9
10
11
12
13

在AnnotatedBeanDefinitionReader类的doRegisterBean()方法中,会调用scopeMetadataResolver对象的resolveScopeMetadata()方法来获取@Scope注解的元数据,并返回ScopeMetadata类的对象。

(2)解析AnnotationScopeMetadataResolver类的resolveScopeMetadata(BeanDefinition definition)方法

@Override
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {

   ScopeMetadata metadata = new ScopeMetadata();
   if (definition instanceof AnnotatedBeanDefinition annDef) {
     AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(annDef.getMetadata(), this.scopeAnnotationType);
     if (attributes != null) {
       metadata.setScopeName(attributes.getString("value"));
       ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
    
       if (proxyMode == ScopedProxyMode.DEFAULT) {
         proxyMode = this.defaultProxyMode;
       }
       metadata.setScopedProxyMode(proxyMode);
     }
   }

   return metadata;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

在AnnotationScopeMetadataResolver类的resolveScopeMetadata()方法中,会解析传入的BeanDefinition对象中的@Scope注解的信息,将解析出的@Scope注解的信息封装到ScopeMetadata对象中并返回。

(3)回到AnnotatedBeanDefinitionReader类的doRegisterBean(Class beanClass, String name, Class<? extends Annotation>[] qualifiers, Supplier supplier, BeanDefinitionCustomizer[] customizers)方法

在调用AnnotationScopeMetadataResolver类的resolveScopeMetadata()方法获取到scopeMetadata对象后,会将scopeMetadata对象的scopeName属性赋值给abd对象的scope属性。也就是将Bean的作用范围标识赋值给了abd对象的scope属性。

# 调用Bean工厂后置处理器

@Scope注解在Spring源码层面调用Bean工厂后置处理器的流程与@Autowired注解在Spring源码层面调用Bean工厂后置处理器的流程基本相同,只是会多一些@Scope注解在Spring源码层面调用Bean工厂后置处理器的流程时的实现细节。

解析ConfigurationClassBeanDefinitionReader类的loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod)方法

private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {

   /****************省略其他代码****************/

   ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata, 

   /****************省略其他代码****************/

   // Consider scoping
   ScopedProxyMode proxyMode = ScopedProxyMode.NO;
   AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);

   if (attributes != null) {
     beanDef.setScope(attributes.getString("value")); 
     proxyMode = attributes.getEnum("proxyMode");
     if (proxyMode == ScopedProxyMode.DEFAULT) {   
       proxyMode = ScopedProxyMode.NO; 
     }
   }

   // Replace the original bean definition with the target one, if necessary
   BeanDefinition beanDefToRegister = beanDef;
   if (proxyMode != ScopedProxyMode.NO) {
     BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
       new BeanDefinitionHolder(beanDef, beanName), this.registry,
       proxyMode == ScopedProxyMode.TARGET_CLASS);
     beanDefToRegister = new ConfigurationClassBeanDefinition((RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata, beanName);
   }

   if (logger.isTraceEnabled()) {
     logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",
                  configClass.getMetadata().getClassName(), beanName));
   }

   this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

在ConfigurationClassBeanDefinitionReader类的loadBeanDefinitionsForBeanMethod()方法中,会处理@Scope注解。具体的逻辑就是会通过AnnotationConfigUtils类的attributesFor()方法获取@Scope注解的属性信息,将其封装到AnnotationAttributes对象中并返回。

如果获取到的attributes不为空,就会解析@Scope注解的value和proxyMode属性,并将解析出来value值设置到beanDef的scope属性中。随后判断解析出来的@Scope注解的proxyMode属性的值如果等于ScopedProxyMode.DEFAULT,则将其赋值为ScopedProxyMode.NO。随后将beanDef对象赋值给beanDefToRegister对象,判断proxyMode的值如果不等于ScopedProxyMode.NO,则创建beanDefToRegister的代理对象。最终会将beanDefToRegister注册到IOC容器中。

# 获取Bean的流程

(1)解析ScopeTest类的main()方法

public static void main(String[] args) {
    System.out.println("创建IOC容器开始..."); 
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ScopeConfig.class);
    System.out.println("创建IOC容器结束...");
    System.out.println("从IOC容器中第一次获取Bean对象开始...");
    ScopeBean scopeBean = context.getBean(ScopeBean.class);
    System.out.println(scopeBean);
    System.out.println("从IOC容器中第一次获取Bean对象结束...");
    System.out.println("从IOC容器中第二次获取Bean对象开始...");
    scopeBean = context.getBean(ScopeBean.class);
    System.out.println(scopeBean);
    System.out.println("从IOC容器中第二次获取Bean对象结束...");
}
1
2
3
4
5
6
7
8
9
10
11
12
13

(2)解析AbstractApplicationContext类的getBean(Class requiredType)方法

@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
    assertBeanFactoryActive();
    return getBeanFactory().getBean(requiredType);
}
1
2
3
4
5

在AbstractApplicationContext类的getBean(Class requiredType)方法中,会调用beanFactory的getBean()方法获取Bean对象。

(3)解析DefaultListableBeanFactory类的getBean(Class requiredType)方法

@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
   return getBean(requiredType, (Object[]) null);
}
1
2
3
4

在DefaultListableBeanFactory类的getBean(Class requiredType)方法中,会调用另一个重载的getBean()方法。

(4)解析DefaultListableBeanFactory类的getBean(Class requiredType, @Nullable Object... args)方法

@Override
public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {
   Assert.notNull(requiredType, "Required type must not be null");
   Object resolved = resolveBean(ResolvableType.forRawClass(requiredType), args, false);
   if (resolved == null) {
     throw new NoSuchBeanDefinitionException(requiredType);
   }
   return (T) resolved;
}
1
2
3
4
5
6
7
8
9

在DefaultListableBeanFactory类的getBean()方法中,会调用resolveBean()方法获取Bean对象。

(5)解析DefaultListableBeanFactory类的resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull)方法

@Nullable
private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
   NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull);
   if (namedBean != null) {
     return namedBean.getBeanInstance();
   }
   /************省略其他代码************/
   return null;
}
1
2
3
4
5
6
7
8
9

在DefaultListableBeanFactory类的resolveBean()方法中,会调用resolveNamedBean()方法获取封装Bean对象NamedBeanHolder对象。

(6)解析DefaultListableBeanFactory类的resolveNamedBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull)方法

@Nullable
private <T> NamedBeanHolder<T> resolveNamedBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {
    Assert.notNull(requiredType, "Required type must not be null");
    String[] candidateNames = getBeanNamesForType(requiredType);
    
    /***********省略其他代码*************/
    if (candidateNames.length == 1) {
        return resolveNamedBean(candidateNames[0], requiredType, args);
    }
    /***********省略其他代码*************/
    
    return null;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

由于在案例程序中的ScopeConfig类中,只提供了一个标注了@Bean注解的方法,所以,这里会进入candidateNames.length (opens new window) == 1的条件分支,会调用另一个重载的resolveNamedBean()方法。

(7)解析DefaultListableBeanFactory类的resolveNamedBean(String beanName, ResolvableType requiredType, @Nullable Object[] args)方法

@Nullable
private <T> NamedBeanHolder<T> resolveNamedBean(String beanName, ResolvableType requiredType, @Nullable Object[] args) throws BeansException {
    Object bean = getBean(beanName, null, args);
    if (bean instanceof NullBean) {
        return null;
    }  
   return new NamedBeanHolder<>(beanName, adaptBeanInstance(beanName, bean, requiredType.toClass()));
}
1
2
3
4
5
6
7
8

在DefaultListableBeanFactory类的resolveNamedBean()方法中,会调用getBean方法获取Bean对象。

(8)解析AbstractBeanFactory类的getBean(String name, @Nullable Class requiredType, @Nullable Object... args)方法

public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args) throws BeansException {
   return doGetBean(name, requiredType, args, false);
}
1
2
3

在AbstractBeanFactory类的getBean()方法中,会调用doGetBean()方法获取Bean对象。

(9)解析AbstractBeanFactory类的doGetBean(String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly)方法

首先,分析 if 分支的逻辑:

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {

   String beanName = transformedBeanName(name);
   Object beanInstance;
   Object sharedInstance = getSingleton(beanName);

   if (sharedInstance != null && args == null) {
     if (logger.isTraceEnabled()) {
       if (isSingletonCurrentlyInCreation(beanName)) {
         logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
       }
       else {
         logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
       } 
     }
    
     beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }
   else {
     /**********省略其他代码************/
   }
   return adaptBeanInstance(name, beanInstance, requiredType);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

在AbstractBeanFactory类的doGetBean()方法中,首先会通过getSingleton()方法从三级缓存中获取单例Bean对象,如果存在单例Bean对象,并且args参数为null,则调用getObjectForBeanInstance()根据给定的Bean实例来返回对象,最终通过adaptBeanInstance()方法来返回适配的Bean对象。

不管是单例Bean还是原型Bean,开始进入doGetBean()方法时,都会进入else分支。

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {

   String beanName = transformedBeanName(name);
   Object beanInstance;
   Object sharedInstance = getSingleton(beanName);

   if (sharedInstance != null && args == null) {
     /**********省略其他代码**************/
   }
   else {
     /**********省略其他代码**************/
     try {
       /**********省略其他代码**************/
       // Create bean instance.
    
       if (mbd.isSingleton()) {
         sharedInstance = getSingleton(beanName, () -> {
           try {
             return createBean(beanName, mbd, args);
           }
           catch (BeansException ex) {
             destroySingleton(beanName);
             throw ex;
           }
         });
         beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
       }
       else if (mbd.isPrototype()) {
         // It's a prototype -> create a new instance.
         Object prototypeInstance = null;
    
         try {
           beforePrototypeCreation(beanName);
           prototypeInstance = createBean(beanName, mbd, args);
         }
         finally {
           afterPrototypeCreation(beanName);
         }    
         beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
       }
       /**********省略其他代码**************/
     }
     catch (BeansException ex) {
       /**********省略其他代码**************/
       throw ex;
     }
     finally {
       beanCreation.end();
     }
   }
   return adaptBeanInstance(name, beanInstance, requiredType);
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

在AbstractBeanFactory类的doGetBean()方法的else分支中,不管是单例Bean还是原型Bean的执行逻辑,都会调用createBean()方法创建Bean对象,并且在原型Bean的情况下,每次都会创建一个新的Bean对象。

(10)解析AbstractAutowireCapableBeanFactory类的createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)方法

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    /**********省略其他代码**************/
   try {
     Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    
     if (logger.isTraceEnabled()) {
       logger.trace("Finished creating instance of bean '" + beanName + "'");
     }
     return beanInstance;
   }
   catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
     throw ex;
   }
   catch (Throwable ex) {
     throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

在AbstractAutowireCapableBeanFactory类的createBean()方法中,会调用doCreateBean()方法创建Bean对象。

(11)解析AbstractAutowireCapableBeanFactory类的doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)方法

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;

   if (mbd.isSingleton()) {
     instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }

   if (instanceWrapper == null) {
     instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   Object bean = instanceWrapper.getWrappedInstance();
   Class<?> beanType = instanceWrapper.getWrappedClass();

   if (beanType != NullBean.class) {
     mbd.resolvedTargetType = beanType;
   }
   // Allow post-processors to modify the merged bean definition.
   synchronized (mbd.postProcessingLock) {
     if (!mbd.postProcessed) {
       try {
         applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
       }
       catch (Throwable ex) {
         /*************省略其他代码*************/
       }
       mbd.markAsPostProcessed();
     }
   }
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));

   if (earlySingletonExposure) {

     /*************省略其他代码*************/
     addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
   }
   // Initialize the bean instance.
   Object exposedObject = bean;

   try {
     populateBean(beanName, mbd, instanceWrapper);
     exposedObject = initializeBean(beanName, exposedObject, mbd);
   }
   catch (Throwable ex) {
    /*************省略其他代码*************/
   }
   if (earlySingletonExposure) {
     Object earlySingletonReference = getSingleton(beanName, false);
     if (earlySingletonReference != null) {
       if (exposedObject == bean) {
         exposedObject = earlySingletonReference;
       }
       else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
         String[] dependentBeans = getDependentBeans(beanName);
         Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
         for (String dependentBean : dependentBeans) {
           if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
             actualDependentBeans.add(dependentBean);
           }
         }
         if (!actualDependentBeans.isEmpty()) {
           /*************省略其他代码*************/
         }
       }
     }
   }
   // Register bean as disposable.
   try {
     registerDisposableBeanIfNecessary(beanName, bean, mbd);
   }
   catch (BeanDefinitionValidationException ex) {
     /*************省略其他代码*************/
   }
   return exposedObject;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

AbstractAutowireCapableBeanFactory类的doCreateBean()方法主要分析以下的主体逻辑。

1)判断如果mbd对象中标注的是单例Bean,则通过beanName移除factoryBeanInstanceCache缓存中的BeanWrapper对象,并将其赋值给instanceWrapper变量。

if (mbd.isSingleton()) {
   instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
1
2
3

2)如果instanceWrapper变量为null,则直接调用createBeanInstance()方法创建Bean实例对象并将其封装到BeanWrapper对象中,赋值给instanceWrapper变量。

if (instanceWrapper == null) {
   instanceWrapper = createBeanInstance(beanName, mbd, args);
}
1
2
3

3)从instanceWrapper变量中取出Bean实例赋值给bean变量,从instanceWrapper变量中取出Bean的Class对象赋值给beanType变量。

Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
1
2

4)将bean变量的值赋值给exposedObject变量。

Object exposedObject = bean;
1

5)为Bean对象的属性赋值,并初始化Bean对象。

populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
1
2

6)如果是原型Bean,则调用registerDisposableBeanIfNecessary()方法向IOC容器中注入一个可任意处理的Bean后直接返回exposedObject。实际上,默认就是返回的调用createBeanInstance()方法新创建的bean对象。

try {
   registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
   throw new BeanCreationException(
     mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
1
2
3
4
5
6
7
8

Spring中的原型Bean,在每次从IOC容器中获取Bean对象时,都会新建一个Bean对象。

7)如果是单例Bean,则会调用getSingleton()方法获取单例Bean,如果获取的单例Bean不为空,并且exposedObject变量与bean变变量相等,说明在调用initializeBean()方法对Bean对象进行初始化时,并没有改变Bean对象的信息,此时,就会将调用getSingleton()方法获取到的单例Bean赋值给exposedObject。随后调用registerDisposableBeanIfNecessary()方法向IOC容器中注入一个可任意处理的Bean后直接返回exposedObject。

if (earlySingletonExposure) {
   Object earlySingletonReference = getSingleton(beanName, false);
   if (earlySingletonReference != null) {
     if (exposedObject == bean) {
       exposedObject = earlySingletonReference;
     }
     /*************省略其他代码*************/
   }
}
try {
   registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
   throw new BeanCreationException(
     mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

所以,如果是单例Bean,没有标注@Lazy注解时,在IOC容器启动的时候就会创建Bean对象。如果单例Bean标注了@Lazy注解,则会在第一次从IOC容器中获取Bean的时,创建Bean对象,随后,每次从IOC容器中获取Bean对象时,都会获取到相同的Bean对象。

# 思考

# 1. @Scope注解的使用场景

@Scope注解的使用场景非常广泛,主要包括以下几种:

  1. 单例(Singleton):默认情况下,Spring容器中的Bean都是单例的,即在整个容器中只存在一个Bean实例。这对于无状态的Bean(如服务层和数据访问层)非常有用,因为它们可以在多个请求之间共享。
  2. 原型(Prototype):当需要每次请求都获得一个新的Bean实例时,可以使用@Scope("prototype")。这适用于需要独立状态的Bean,如表单对象或数据传输对象。
  3. Web作用域:Spring还提供了Web作用域,包括request、session和globalSession。这些作用域仅适用于Web应用,允许Bean的实例与HTTP请求、会话或全局会话相关联。
    • request:每次HTTP请求都会创建一个新的Bean实例,仅在该请求内有效。
    • session:每个HTTP会话都会创建一个新的Bean实例,仅在该会话内有效。
    • globalSession:在基于portlet的Web应用中,类似于标准的HTTP Session作用域。
  4. 自定义作用域:开发者还可以定义自己的作用域,以满足特定的应用需求。

# 2. @Scope注解在Spring内部的执行流程

@Scope注解在Spring内部的执行流程大致如下:

  1. 解析注解:Spring容器在启动时,会扫描并解析所有的Bean定义,包括带有@Scope注解的Bean。
  2. 确定作用域:根据@Scope注解的value属性值,确定Bean的作用范围。
  3. 创建Bean实例:根据确定的作用范围,Spring容器会按照相应的策略来创建Bean实例。例如,对于单例Bean,Spring容器会在启动时创建并缓存一个实例;对于原型Bean,则会在每次请求时创建一个新的实例。
  4. 注入依赖:如果Bean之间存在依赖关系,Spring容器会按照依赖注入的原则,将依赖的Bean注入到相应的字段或方法中。
  5. 管理Bean的生命周期:Spring容器会管理Bean的整个生命周期,包括创建、使用和销毁。

# 3. @Scope是如何创建代理类的

当@Scope注解与代理模式结合使用时(例如,在Web作用域中),Spring会通过代理机制来创建Bean的代理类。这主要是因为Web作用域的Bean需要与HTTP请求、会话等生命周期相关联,而直接创建的Bean实例无法满足这种需求。

创建代理类的流程大致如下:

  1. 解析@Scope注解:Spring容器在解析Bean定义时,会检查@Scope注解的proxyMode属性。如果该属性被设置为ScopedProxyMode.TARGET_CLASS或ScopedProxyMode.INTERFACES,则表示需要创建代理类。
  2. 创建代理Bean定义:对于需要代理的Bean,Spring会创建一个新的Bean定义(ProxyBeanDefinition),该定义描述了代理类的信息。
  3. 生成代理类:Spring使用动态代理技术(如JDK动态代理或CGLIB)来生成代理类的字节码,并加载到JVM中。
  4. 注册代理Bean:生成的代理Bean会被注册到Spring容器中,并与原始Bean的ID相关联(通常是在原始Bean的ID前加上scopedTarget.前缀)。
  5. 使用代理Bean:当应用程序通过Spring容器获取Bean时,如果Bean被配置为代理模式,则实际上获取到的是代理Bean的实例。代理Bean会拦截对原始Bean的调用,并根据当前的作用域(如HTTP请求或会话)来转发这些调用。

# 1.16 @PostConstruct注解与@PreDestroy注解

@PostConstruct注解与@PreDestroy注解都是JSR250规范中提供的注解。@PostConstruct注解标注的方法可以在创建Bean后在为属性赋值后,初始化Bean之前执行,@PreDestroy注解标注的方法可以在Bean销毁之前执行。在Spring6中,如果使用@PostConstruct注解与@PreDestroy注解,则需要在Maven的pom.xml文件中添加如下依赖。

<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>2.1.1</version>
</dependency>
1
2
3
4
5

# 注解源码

1.@PostConstruct注解

@PostConstruct注解的源码详见:jakarta.annotation.PostConstruct。

@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}
1
2
3
4
5

@PostConstruct注解通常被用来指定一些Bean对象的初始化操作。

2.@PreDestroy注解

@PreDestroy注解的源码详见:jakarta.annotation.PreDestroy。

@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PreDestroy {
}。
1
2
3
4
5

@PreDestroy注解通常被用来实现在Bean销毁之前执行的一些操作,比如释放资源、释放数据库连接等操作。

# 源码时序图

# @PostConstruct源码时序图

1.16.1

1.16.2

# @PreDestroy源码时序图

1.16.3

1.16.4

# 源码解析

# @PostConstruct源码解析

(1)解析AbstractAutowireCapableBeanFactory类的initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd)方法

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
   /*************省略其他代码**********/
   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) {
     wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }
    /*************省略其他代码**********/
   return wrappedBean;
}
1
2
3
4
5
6
7
8
9

在AbstractAutowireCapableBeanFactory类的initializeBean()方法中,调用Bean的初始化方法之前,会调用applyBeanPostProcessorsBeforeInitialization()方法进行处理。

(2)解析AbstractAutowireCapableBeanFactory类的applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)方法

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {

   Object result = existingBean;
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
     Object current = processor.postProcessBeforeInitialization(result, beanName);
     if (current == null) {
       return result;
     }
     result = current;
   }
   return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

在AbstractAutowireCapableBeanFactory类的applyBeanPostProcessorsBeforeInitialization()方法中,会循环遍历所有的BeanPostProcessor对象,调用BeanPostProcessor对象的postProcessBeforeInitialization()方法获取Bean对象,如果获取到的Bean对象为空,则直接返回。否则,继续循环调用BeanPostProcessor对象的postProcessBeforeInitialization()方法。

(3)解析InitDestroyAnnotationBeanPostProcessor类的postProcessBeforeInitialization(Object bean, String beanName)方法

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

   LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
   try {
     metadata.invokeInitMethods(bean, beanName);
   }
   catch (InvocationTargetException ex) {
    /**********省略其他代码***********/
   }
   catch (Throwable ex) {
    /**********省略其他代码***********/
   }
   return bean;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在InitDestroyAnnotationBeanPostProcessor类的postProcessBeforeInitialization()方法中,会调用findLifecycleMetadata()方法查找生命周期相关的注解元数据。

(4)解析InitDestroyAnnotationBeanPostProcessor类的findLifecycleMetadata(Class<?> clazz)方法

private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
   if (this.lifecycleMetadataCache == null) {
     return buildLifecycleMetadata(clazz);
   }
   LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
   if (metadata == null) {
     synchronized (this.lifecycleMetadataCache) {
       metadata = this.lifecycleMetadataCache.get(clazz);
       if (metadata == null) {
         metadata = buildLifecycleMetadata(clazz);
         this.lifecycleMetadataCache.put(clazz, metadata);
       }
       return metadata;
     }
   }
   return metadata;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在InitDestroyAnnotationBeanPostProcessor类的findLifecycleMetadata()方法中,如果lifecycleMetadataCache缓存为null,则直接调用buildLifecycleMetadata()方法构建生命周期元数据并返回。否则,先从lifecycleMetadataCache缓存中获取LifecycleMetadata对象,如果获取到的LifecycleMetadata对象为空,则调用buildLifecycleMetadata()方法构建生命周期元数据,并将其存放到lifecycleMetadataCache缓存中。

(5)解析InitDestroyAnnotationBeanPostProcessor类的buildLifecycleMetadata(final Class<?> clazz)方法

private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
   if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
     return this.emptyLifecycleMetadata;
   }
   List<LifecycleElement> initMethods = new ArrayList<>();
   List<LifecycleElement> destroyMethods = new ArrayList<>();
   Class<?> targetClass = clazz;
   do {
     final List<LifecycleElement> currInitMethods = new ArrayList<>();
     final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
     ReflectionUtils.doWithLocalMethods(targetClass, method -> {
       if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
         LifecycleElement element = new LifecycleElement(method);
         currInitMethods.add(element);
         if (logger.isTraceEnabled()) {
           logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
         }
       }
       if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
         currDestroyMethods.add(new LifecycleElement(method));
         if (logger.isTraceEnabled()) {
           logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
         }
       }
     });
     initMethods.addAll(0, currInitMethods);
     destroyMethods.addAll(currDestroyMethods);
     targetClass = targetClass.getSuperclass();
   }
   while (targetClass != null && targetClass != Object.class);
   return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
       new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

在InitDestroyAnnotationBeanPostProcessor类的buildLifecycleMetadata()方法中,首先,查看类中如果没有被@PostConstruct注解和@PreDestroy注解标注的方法,则直接返回emptyLifecycleMetadata对象。否则,循环类中的所有方法,判断方法上是否标注了@PostConstruct注解,如果标注了@PostConstruct注解,则将当前方法封装到element对象中,并将element对象添加到currInitMethods集合中,并将currInitMethods集合添加到initMethods集合中。同理,会将标注了@PreDestroy注解的方法封装到LifecycleElement类的对象中,并添加到destroyMethods集合中。

initAnnotationType和destroyAnnotationType的值是在CommonAnnotationBeanPostProcessor类的构造方法中赋值的:

public CommonAnnotationBeanPostProcessor() {
   setOrder(Ordered.LOWEST_PRECEDENCE - 3);
   setInitAnnotationType(PostConstruct.class);
   setDestroyAnnotationType(PreDestroy.class);
   // java.naming module present on JDK 9+?
   if (jndiPresent) {
     this.jndiFactory = new SimpleJndiBeanFactory();
   }
}
1
2
3
4
5
6
7
8
9

在CommonAnnotationBeanPostProcessor类的构造方法中,调用setInitAnnotationType()方法将initAnnotationType赋值为@PostConstruct注解的Class对象。调用setDestroyAnnotationType()方法将destroyAnnotationType赋值为@PreDestroy注解的Class对象。

(6)返回InitDestroyAnnotationBeanPostProcessor类的postProcessBeforeInitialization(Object bean, String beanName)方法

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
   LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
   try {
     metadata.invokeInitMethods(bean, beanName);
   }
   /***********省略其他代码**********/
   return bean;
}
1
2
3
4
5
6
7
8
9

在InitDestroyAnnotationBeanPostProcessor类的postProcessBeforeInitialization()方法中,会调用查找到的metadata对象的invokeInitMethods()方法来执行初始化方法。

(7)解析LifecycleMetadata类的invokeInitMethods(Object target, String beanName)方法

public void invokeInitMethods(Object target, String beanName) throws Throwable {
   Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
   Collection<LifecycleElement> initMethodsToIterate = (checkedInitMethods != null ? checkedInitMethods : this.initMethods);
   if (!initMethodsToIterate.isEmpty()) {
     for (LifecycleElement element : initMethodsToIterate) {
       /********省略其他代码*************/
       element.invoke(target);
     }
   }
}
1
2
3
4
5
6
7
8
9
10

在LifecycleMetadata类的invokeInitMethods()方法中,会循环遍历initMethodsToIterate集合,并调用遍历出的每个element对象的invoke()方法。

(8)解析LifecycleElement类的invoke(Object target)方法

public void invoke(Object target) throws Throwable {
   ReflectionUtils.makeAccessible(this.method);
   this.method.invoke(target, (Object[]) null);
}
1
2
3
4

在LifecycleElement类的invoke()方法中,会通过Java反射调用标注了@PostConstruct注解的方法。就会调用PrePostBean类的postConstruct()方法。

# @PreDestroy源码解析

(1)解析DisposableBeanAdapter类的destroy()方法

@Override
public void destroy() {
   if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
     for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
       processor.postProcessBeforeDestruction(this.bean, this.beanName);
     }
   }
    /************省略其他代码**************/
}
1
2
3
4
5
6
7
8
9

在DisposableBeanAdapter类的destroy()方法中,会遍历beanPostProcessors集合,调用每个processor对象的postProcessBeforeDestruction()方法执行Bean销毁前的操作。

(2)解析InitDestroyAnnotationBeanPostProcessor类的postProcessBeforeDestruction(Object bean, String beanName)方法

@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {

   LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
   try {
     metadata.invokeDestroyMethods(bean, beanName);
   }
   catch (InvocationTargetException ex) {
    /***********省略其他代码************/
   }
   catch (Throwable ex) {
     /***********省略其他代码************/
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

InitDestroyAnnotationBeanPostProcessor类的postProcessBeforeDestruction()方法中,也会调用findLifecycleMetadata()方法来查找与Bean的生命周期有关的注解,执行逻辑与本章5.1节中调用findLifecycleMetadata()方法的逻辑相同,这里不再赘述。后续会调用通过findLifecycleMetadata()方法获取到的metadata对象的invokeDestroyMethods()方法来执行销毁方法。

(3)解析LifecycleMetadata类的invokeDestroyMethods(Object target, String beanName)方法

public void invokeDestroyMethods(Object target, String beanName) throws Throwable {
   Collection<LifecycleElement> checkedDestroyMethods = this.checkedDestroyMethods;
   Collection<LifecycleElement> destroyMethodsToUse = (checkedDestroyMethods != null ? checkedDestroyMethods : this.destroyMethods);

   if (!destroyMethodsToUse.isEmpty()) {
     for (LifecycleElement element : destroyMethodsToUse) {
       if (logger.isTraceEnabled()) {
         logger.trace("Invoking destroy method on bean '" + beanName + "': " + element.getMethod());
       }
       element.invoke(target);
     }
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

在LifecycleMetadata类的invokeDestroyMethods()方法中,会遍历所有标注了@PreDestroy注解的方法,并执行对应的方法。

(4)解析LifecycleElement类的invoke(Object target)方法

public void invoke(Object target) throws Throwable {
   ReflectionUtils.makeAccessible(this.method);
   this.method.invoke(target, (Object[]) null);
}
1
2
3
4

在LifecycleElement类的invoke()方法中,会通过Java反射的方式调用对应的方法。就是调用PrePostBean类的preDestroy()方法。

# 思考

Bean的初始化的完整过程

1.16.5

# 二. AOP切面

# 2.1 @EnableAspectJAutoProxy注解

@EnableAspectJAutoProxy注解表示开启Spring对基于注解的AOP的支持,需要使用AOP功能,就需要使用@EnableAspectJAutoProxy注解来开启AOP功能。

# 注解源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
    boolean proxyTargetClass() default false;
    /**
     * @since 4.3.1
     */
    boolean exposeProxy() default false;
}
1
2
3
4
5
6
7
8
9
10
11
  • proxyTargetClass:表示是否基于CGLib进行代理。true:表示基于CGLib进行代理。false:表示基于JDK进行代理。默认值为false。

  • exposeProxy:从Spring4.3.1版本开始提供的属性,表示是否对外暴露代理对象。true:对外暴露代理对象,可以通过AopContext进行访问。false:不对外暴露代理对象。默认值为false。

# 源码时序图

通过@EnableAspectJAutoProxy注解的源码可以发现,在@EnableAspectJAutoProxy注解的源码上使用@Import注解导入了AspectJAutoProxyRegistrar类。在导入的AspectJAutoProxyRegistrar类后,核心的逻辑就是解析AnnotationAwareAspectJAutoProxyCreator类。所以加载@EnableAspectJAutoProxy注解可以分成两部分进行解析,一部分是注册AnnotationAwareAspectJAutoProxyCreator类,一部分是解析AnnotationAwareAspectJAutoProxyCreator类。

# 注册AnnotationAwareAspectJAutoProxyCreator类

2.1.1

2.1.2

2.1.3

# 解析AnnotationAwareAspectJAutoProxyCreator类

2.1.5

# 源码解析

# 注册AnnotationAwareAspectJAutoProxyCreator类

(1)解析ConfigurationClassPostProcessor类的processConfigBeanDefinitions(BeanDefinitionRegistry registry)方法

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
   /*************省略其他代码**************/
   do {
     StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
     parser.parse(candidates);
     parser.validate();
     /*************省略其他代码**************/
   }
   while (!candidates.isEmpty());
  /*************省略其他代码**************/
}
1
2
3
4
5
6
7
8
9
10
11

在ConfigurationClassPostProcessor类的processConfigBeanDefinitions()方法中,调用了parser的parse()方法进行解析。

(2)解析ConfigurationClassParser类的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)方法

@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException {

    /***********省略其他代码*************/

   // Process any @Import annotations
   processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
   /***********省略其他代码*************/
   return null;
}
1
2
3
4
5
6
7
8
9
10

由于在@EnableAspectJAutoProxy注解上使用@Import注解导入了AspectJAutoProxyRegistrar类的Class对象,所以,在ConfigurationClassParser类的doProcessConfigurationClass()方法中,重点分析processImports()方法。

(3)解析ConfigurationClassParser类的processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection importCandidates, Predicate exclusionFilter, boolean checkForCircularImports)方法

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter, boolean checkForCircularImports) {
  /**********省略其他代码***********/

   else {
     this.importStack.push(configClass);
     try {    
       for (SourceClass candidate : importCandidates) {
         /**********省略其他代码***********/
         else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
           Class<?> candidateClass = candidate.loadClass();
           ImportBeanDefinitionRegistrar registrar =
             ParserStrategyUtils.instantiateClass(candidateClass,  ImportBeanDefinitionRegistrar.class, this.environment, this.resourceLoader, this.registry);
           configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
         }
         /**********省略其他代码***********/
       }
     }
    /**********省略其他代码***********/
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

在ConfigurationClassParser类的processImports()方法中,会循环importCandidates集合处理每一个SourceClass对象。因为在@EnableAspectJAutoProxy注解上使用@Import注解导入的AspectJAutoProxyRegistrar类实现了ImportBeanDefinitionRegistrar接口,所以代码会执行到else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class))逻辑中。进而调用configClass的addImportBeanDefinitionRegistrar()方法来导入BeanDefinitionRegistrar。

(4)解析ConfigurationClass类的addImportBeanDefinitionRegistrar(ImportBeanDefinitionRegistrar registrar, AnnotationMetadata importingClassMetadata)方法

void addImportBeanDefinitionRegistrar(ImportBeanDefinitionRegistrar registrar, AnnotationMetadata importingClassMetadata) {
   this.importBeanDefinitionRegistrars.put(registrar, importingClassMetadata);
}
1
2
3

在ConfigurationClass类的addImportBeanDefinitionRegistrar()方法中,会调用importBeanDefinitionRegistrars的put()方法,将registrar作为Key,importingClassMetadata作为value存储起来。

private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars = new LinkedHashMap<>();
1

(5)返回ConfigurationClassPostProcessor类的processConfigBeanDefinitions(BeanDefinitionRegistry registry)方法

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
   /**********省略其他代码**********/
   do {
     /**********省略其他代码**********/
     this.reader.loadBeanDefinitions(configClasses);
     /**********省略其他代码**********/
   } while (!candidates.isEmpty());
    /**********省略其他代码**********/
}
1
2
3
4
5
6
7
8
9

在ConfigurationClassPostProcessor类的processConfigBeanDefinitions()方法中,调用了reader的loadBeanDefinitions()方法加载Bean的定义信息。

(6)解析ConfigurationClassBeanDefinitionReader类的loadBeanDefinitions(Set configurationModel)方法

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
   TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
   for (ConfigurationClass configClass : configurationModel) {
     loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
   }
}
1
2
3
4
5
6

在ConfigurationClassBeanDefinitionReader类的loadBeanDefinitions()方法中,调用了loadBeanDefinitionsForConfigurationClass()方法为配置类加载Bean定义信息。

(7)解析ConfigurationClassBeanDefinitionReader类的loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator)方法

private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
    /*************省略其他代码*************/
   loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
1
2
3
4

在ConfigurationClassBeanDefinitionReader类的loadBeanDefinitionsForConfigurationClass()方法中,首先,调用configClass的getImportBeanDefinitionRegistrars()获取导入的BeanDefinitionRegistrars,并将其传入到loadBeanDefinitionsFromRegistrars()方法中来加载Bean定义信息。

(8)解析ConfigurationClass类的getImportBeanDefinitionRegistrars()方法

Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> getImportBeanDefinitionRegistrars() {
   return this.importBeanDefinitionRegistrars;
}
1
2
3

ConfigurationClass类的getImportBeanDefinitionRegistrars()直接返回了importBeanDefinitionRegistrars这个Map集合。

(9)解析ConfigurationClassBeanDefinitionReader类的loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars)方法

private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
   registrars.forEach((registrar, metadata) -> registrar.registerBeanDefinitions(metadata, this.registry,this.importBeanNameGenerator));
}
1
2
3

在ConfigurationClassBeanDefinitionReader类的loadBeanDefinitionsFromRegistrars()方法中,通过Lambda表达式循环遍历了Map集合registrars,并调用registrar的registerBeanDefinitions()方法注册Bean定义信息。

(10)解析ImportBeanDefinitionRegistrar接口的registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator)方法

default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,BeanNameGenerator importBeanNameGenerator) {
    registerBeanDefinitions(importingClassMetadata, registry);
}
1
2
3

ImportBeanDefinitionRegistrar接口的registerBeanDefinitions()方法中,调用了另一个重载的registerBeanDefinitions()方法。

(11)解析AspectJAutoProxyRegistrar类的registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)方法

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
   AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
   AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
   if (enableAspectJAutoProxy != null) {
     if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
       AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
     }
     if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
       AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
     }
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

在AspectJAutoProxyRegistrar类的registerBeanDefinitions()方法中,首先会调用AopConfigUtils类的registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法如果有必要则注册AspectJ注解自动代理创建器。随后解析元数据中的@EnableAspectJAutoProxy注解,判断是否基于CGLib创建代理,是否对外暴露代理对象,并处理相关逻辑。

(12)解析AopConfigUtils类的registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry)方法。

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
   return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
1
2
3
4

在AopConfigUtils类的registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法中,调用了另一个重载的registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法。

(13)解析AopConfigUtils类的registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source)方法

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
1
2
3
4

调用了registerOrEscalateApcAsRequired()方法来注册AnnotationAwareAspectJAutoProxyCreator类。

(14)解析AopConfigUtils类的registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source)方法

@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
   if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
     BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
     if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
       int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
       int requiredPriority = findPriorityForClass(cls);
       if (currentPriority < requiredPriority) {
         apcDefinition.setBeanClassName(cls.getName());
       }
     }
     return null;
   }
   RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
   beanDefinition.setSource(source);
   beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
   beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
   registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
   return beanDefinition;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

在AopConfigUtils类的registerOrEscalateApcAsRequired()方法中,将AnnotationAwareAspectJAutoProxyCreator类封装成RootBeanDefinition对象,并将RootBeanDefinition对象注册到IOC容器中。

# 解析AnnotationAwareAspectJAutoProxyCreator类

(1)解析AbstractAutowireCapableBeanFactory类的initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd)方法

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    /***********省略其他代码***********/
    
    try {
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在AbstractAutowireCapableBeanFactory类的initializeBean()方法中,调用初始化方法后,在满足条件时,调用applyBeanPostProcessorsAfterInitialization()方法执行初始化之后的一些业务逻辑处理。

(2)解析AbstractAutowireCapableBeanFactory类的applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)方法

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {

   Object result = existingBean;
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
     Object current = processor.postProcessAfterInitialization(result, beanName);
    
     if (current == null) {
       return result;
     }
    
     result = current;
   }

   return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

在AbstractAutowireCapableBeanFactory类的applyBeanPostProcessorsAfterInitialization()方法中,遍历所有的Bean的后置处理器,调用每个后置处理器的postProcessAfterInitialization()方法执行后置处理。只要检测到有一个后置处理器执行的结果数据为null,就直接返回结果,不再执行后续处理器的逻辑。否则,直到执行完所有后置处理器的逻辑处理。

(3)解析AbstractAutoProxyCreator类的postProcessAfterInitialization(@Nullable Object bean, String beanName)方法

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
   if (bean != null) {
     Object cacheKey = getCacheKey(bean.getClass(), beanName);
     if (this.earlyProxyReferences.remove(cacheKey) != bean) {
       return wrapIfNecessary(bean, beanName, cacheKey);
     }
   }
   return bean;
}
1
2
3
4
5
6
7
8
9
10

在AbstractAutoProxyCreator类的postProcessAfterInitialization()方法中,调用getCacheKey()方法获取缓存的Key,随后检测earlyProxyReferences中的Key不等于bean时,就调用wrapIfNecessary()方法检测是否增强处理。

(4)解析AbstractAutoProxyCreator类的getCacheKey(Class<?> beanClass, @Nullable String beanName)方法

protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) {
    if (StringUtils.hasLength(beanName)) {
        return (FactoryBean.class.isAssignableFrom(beanClass) ? BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
    }
    else {
        return beanClass;
    }
}
1
2
3
4
5
6
7
8

在AbstractAutoProxyCreator类的getCacheKey()方法中,如果beanName不为空,检测beanClass是否是FactoryBean,如果beanClass是FactoryBean,则在beanName前加BeanFactory.FACTORY_BEAN_PREFIX前缀返回结果,否则,直接返回beanName。如果beanName为空,则直接返回beanClass。

(5)解析AbstractAutoProxyCreator类的wrapIfNecessary(Object bean, String beanName, Object cacheKey)

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
   if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
     return bean;
   }
   if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
     return bean;
   }
   if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
     this.advisedBeans.put(cacheKey, Boolean.FALSE);
     return bean;
   }
   // Create proxy if we have advice.
   Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
   if (specificInterceptors != DO_NOT_PROXY) {
     this.advisedBeans.put(cacheKey, Boolean.TRUE);
     Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
     this.proxyTypes.put(cacheKey, proxy.getClass());
     return proxy;
   }
   this.advisedBeans.put(cacheKey, Boolean.FALSE);
   return bean;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

在AbstractAutoProxyCreator类的wrapIfNecessary()中,如果对当前Bean进行过AOP增强处理,则直接返回当前Bean。如果不需要对当前Bean进行AOP增强处理,则直接返回当前Bean。接下来,就是判断当前Bean如果是基础设施类,或者配置了跳过自动代理,则将cacheKey为Key,Boolean.FALSE为value存入advisedBeans中,直接返回当前Bean。

接下来,调用getAdvicesAndAdvisorsForBean()方法获取需要AOP增强的方法,获取到要AOP增强的方法后,对这些需要增强的方法创建代理对象。

(6)解析AbstractAutoProxyCreator类的isInfrastructureClass(Class<?> beanClass)方法

protected boolean isInfrastructureClass(Class<?> beanClass) {
   boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
     Pointcut.class.isAssignableFrom(beanClass) || 
       Advisor.class.isAssignableFrom(beanClass) ||
         AopInfrastructureBean.class.isAssignableFrom(beanClass);
   if (retVal && logger.isTraceEnabled()) {
     logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
   }
   return retVal;
}
1
2
3
4
5
6
7
8
9
10

AbstractAutoProxyCreator类的isInfrastructureClass()方法主要是判断当前类是否是基础设施类。在AbstractAutoProxyCreator类的isInfrastructureClass()方法中,判断如果传入的beanClass是Advice类型、或者是Pointcut类型,或者是Advisor类型,或者是AopInfrastructureBean类型,则返回true,表示是基础设施类,否则,返回false,不是基础设施类。

(7)解析AbstractAdvisorAutoProxyCreator类的getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource)方法

@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
   List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
   if (advisors.isEmpty()) {
     return DO_NOT_PROXY;
   }
   return advisors.toArray();
}
1
2
3
4
5
6
7
8
9

AbstractAdvisorAutoProxyCreator类的getAdvicesAndAdvisorsForBean()方法的主要作用是获取需要AOP增强的方法,本质上是调用的findEligibleAdvisors()方法获取需要AOP增强的方法,返回List集合后,调用toArray()方法返回数组。

(8)解析AbstractAutoProxyCreator类的createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource)方法

protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) {
   return buildProxy(beanClass, beanName, specificInterceptors, targetSource, false);
}
1
2
3

在方法中直接调用了buildProxy()方法来构建代理对象。

(9)解析AbstractAutoProxyCreator类的buildProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource, boolean classOnly)方法

private Object buildProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource, boolean classOnly) {

   if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
     AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
   }

   ProxyFactory proxyFactory = new ProxyFactory();
   proxyFactory.copyFrom(this);

   if (proxyFactory.isProxyTargetClass()) {
     // Explicit handling of JDK proxy targets and lambdas (for introduction advice scenarios)
     if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) {
       // Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
       for (Class<?> ifc : beanClass.getInterfaces()) {
         proxyFactory.addInterface(ifc);
       }
     }
   }
   else {
     // No proxyTargetClass flag enforced, let's apply our default checks...
    
     if (shouldProxyTargetClass(beanClass, beanName)) {
       proxyFactory.setProxyTargetClass(true);
     }
     else {
       evaluateProxyInterfaces(beanClass, proxyFactory);
     }
   }

   Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
   proxyFactory.addAdvisors(advisors);
   proxyFactory.setTargetSource(targetSource);
   customizeProxyFactory(proxyFactory);

   proxyFactory.setFrozen(this.freezeProxy);
   if (advisorsPreFiltered()) {
     proxyFactory.setPreFiltered(true);
   }
   // Use original ClassLoader if bean class not locally loaded in overriding class loader
   ClassLoader classLoader = getProxyClassLoader();
   if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
     classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
   }
   return (classOnly ? proxyFactory.getProxyClass(classLoader) : proxyFactory.getProxy(classLoader));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

在AbstractAutoProxyCreator类的buildProxy()方法中,会调用proxyFactory的getProxy()方法真正创建代理对象。

(10)解析ProxyFactory类的getProxy(@Nullable ClassLoader classLoader)方法

public Object getProxy(@Nullable ClassLoader classLoader) {
   return createAopProxy().getProxy(classLoader);
}
1
2
3

在ProxyFactory类的getProxy()方法中,首先调用createAopProxy()方法创建AOP代理,随后调用AOP代理的getProxy()方法获取代理对象。

(11)解析ProxyCreatorSupport类的createAopProxy()方法

protected final synchronized AopProxy createAopProxy() {
   if (!this.active) {
     activate();
   }
   return getAopProxyFactory().createAopProxy(this);
}
1
2
3
4
5
6

在ProxyCreatorSupport类的createAopProxy()方法中,会调用aopProxyFactory的createAopProxy方法创建AOP代理。

(12)解析DefaultAopProxyFactory类的createAopProxy(AdvisedSupport config)方法

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
   if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
     Class<?> targetClass = config.getTargetClass();
     if (targetClass == null) {
       throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation.");
     }
     if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
       return new JdkDynamicAopProxy(config);
     }
     return new ObjenesisCglibAopProxy(config);
   }
   else {
     return new JdkDynamicAopProxy(config);
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

在DefaultAopProxyFactory类的createAopProxy()方法中,会判断如果目标类是接口,或者目标类实现了Proxy接口,或者目标类是由Lambda表达式生成的,就创建基于JDK的AOP动态代理,否则创建基于CGLib的AOP动态代理。默认是创建基于JDK的AOP动态代理。

(13)返回ProxyFactory类的getProxy(@Nullable ClassLoader classLoader)方法,继续跟进getProxy()方法,此时就会根据DefaultAopProxyFactory类的createAopProxy()方法返回的是基于JDK的AOP动态代理,还是基于CGLib的AOP动态代理,则执行JdkDynamicAopProxy类中的getProxy()方法的逻辑,或者执行CglibAopProxy类中的getProxy()方法的逻辑返回代理对象,随后就会执行代理对象中的方法。

# 思考

# 1. @EnableAspectJAutoProxy注解在Spring底层的执行流程

  1. 容器启动与Bean定义扫描:
    • Spring容器启动时,会进行Bean定义的扫描。这包括扫描类路径下的所有组件(如@Component、@Service、@Repository等注解的类),以及配置类(@Configuration注解的类)。
  2. 识别@EnableAspectJAutoProxy注解:
    • 在扫描过程中,Spring会识别出带有@EnableAspectJAutoProxy注解的配置类。这个注解通常位于一个或多个配置类上,用于开启AspectJ的自动代理功能。
  3. 处理@EnableAspectJAutoProxy注解:
    • 由于@EnableAspectJAutoProxy注解通过@Import注解导入了AspectJAutoProxyRegistrar类,Spring会调用AspectJAutoProxyRegistrar的registerBeanDefinitions方法来注册必要的Bean定义。
  4. 注册AnnotationAwareAspectJAutoProxyCreator:
    • 在AspectJAutoProxyRegistrar的registerBeanDefinitions方法中,会调用AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary等方法来注册AnnotationAwareAspectJAutoProxyCreator作为BeanPostProcessor。这个BeanPostProcessor是自动代理功能的核心。
  5. Bean的创建与初始化:
    • 当Spring容器创建Bean时,AnnotationAwareAspectJAutoProxyCreator作为BeanPostProcessor会被调用。它会在Bean的初始化(如@PostConstruct注解的方法执行)之后,但在Bean被返回给使用者之前,检查该Bean是否需要被代理。
  6. 代理对象的创建:
    • 如果需要代理,AnnotationAwareAspectJAutoProxyCreator会根据Bean的配置(如是否实现了接口)来创建相应的代理对象(JDK动态代理或CGLIB代理)。
  7. 应用切面:
    • 代理对象被创建后,Spring AOP会将AspectJ定义的切面应用到这些代理对象上。这样,当代理对象的方法被调用时,相应的切面逻辑(如前置通知、后置通知、环绕通知等)会按照定义的顺序被执行。

# 2. @EnableAspectJAutoProxy注解都做了哪些工作

@EnableAspectJAutoProxy注解主要做了以下几项工作:

  • 开启AspectJ自动代理:通过该注解,Spring容器能够自动识别并使用AspectJ的注解来定义切面、切点和通知。
  • 注册BeanPostProcessor:注册AnnotationAwareAspectJAutoProxyCreator作为BeanPostProcessor,这是实现自动代理的关键。
  • 配置代理创建器:配置AnnotationAwareAspectJAutoProxyCreator,以便它能够根据Bean的配置和AspectJ的注解来创建代理对象。
  • 支持AOP功能:使得Spring容器能够支持AOP的各种功能,如事务管理、日志记录、安全检查等。

# 3. @EnableAspectJAutoProxy注解是如何开启AOP代理的

@EnableAspectJAutoProxy注解通过以下步骤开启AOP代理:

  1. 导入AspectJAutoProxyRegistrar:@EnableAspectJAutoProxy注解通过@Import注解导入了AspectJAutoProxyRegistrar类。
  2. 注册AnnotationAwareAspectJAutoProxyCreator:AspectJAutoProxyRegistrar的registerBeanDefinitions方法被调用时,会注册AnnotationAwareAspectJAutoProxyCreator作为BeanPostProcessor。这个BeanPostProcessor负责在Bean的初始化之后检查是否需要为该Bean创建代理对象。
  3. 自动检测与代理:当Spring容器创建Bean时,AnnotationAwareAspectJAutoProxyCreator会检查该Bean是否满足被代理的条件(如是否标注了@Aspect注解的类中的方法被用作切点)。如果满足条件,则为其创建代理对象。
  4. 应用切面:代理对象被创建后,Spring AOP会将AspectJ定义的切面应用到这些代理对象上。这样,当代理对象的方法被调用时,相应的切面逻辑会被执行。

# 2.2 切入点表达式

切入点表达式一般指的是一种遵循特定语法,用于捕获每一个种类的可使用连接点的语法,并且能够对符合语法格式的连接点进行功能增强。

切入点表达式可以按照用途分成如下种类。

方法执行:execution(MethodSignature)
方法调用:call(MethodSignature)
构造器执行:execution(ConstructorSignature)
构造器调用:call(ConstructorSignature)
类初始化:staticinitialization(TypeSignature)
属性读操作:get(FieldSignature)
属性写操作:set(FieldSignature)
例外处理执行:handler(TypeSignature)
对象初始化:initialization(ConstructorSignature)
对象预先初始化:preinitialization(ConstructorSignature)
1
2
3
4
5
6
7
8
9
10

Spring支持的AspectJ切入点关键字如下所示:

execution:用于匹配方法执行的连接点
within:用于匹配指定类型内的方法执行
this:用于匹配当前AOP代理对象类型的执行方法注意是AOP代理对象的类型匹配,这样就可能包括引入接口类型匹配
target:用于匹配当前目标对象类型的执行方法注意是目标对象的类型匹配,这样就不包括引入接口类型匹配
args:用于匹配当前执行的方法传入的参数为指定类型的执行方法
@within:用于匹配所以持有指定注解类型内的方法
@target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解
@args:用于匹配当前执行的方法传入的参数,持有指定的注解
@annotation:用于匹配当前持有指定注解的执行方法
bean:Spring AOP扩展的,AspectJ没有此指示符,用于匹配特定名称的Bean对象的执行方法
reference pointcut:表示引用其他命名的切入点,只有@ApectJ风格支持,Schema风格不支持。
1
2
3
4
5
6
7
8
9
10
11

Spring支持的切入点表达式的通配符如下所示。

*:匹配任何数量字符;
..:匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数。
+:匹配指定类型的子类型;仅能作为后缀放在类型模式后边。
java.lang.String 匹配String类型;
java.*.String 匹配java包下的任何“一级子包”下的String类型;如匹配java.lang.String,但不匹配java.lang.ss.String
java..* 匹配java包及任何子包下的任何类型;如匹配java.lang.String、java.lang.annotation.Annotation
java.lang.*ing 匹配任何java.lang包下的以ing结尾的类型;如匹配java.lang.bingheing
java.lang.Number+ 匹配java.lang包下的任何Number的子类型;如匹配java.lang.Integer,也匹配java.math.BigInteger
1
2
3
4
5
6
7
8

Spring支持的切入点表达式的逻辑条件如下所示。

&& and
|| or
! not
1
2
3

# 源码时序图

切入点表达式在Spring底层执行的源码时序图

2.2.1

2.2.2

2.2.3

2.2.4

# 源码解析

(1)解析AbstractAdvisorAutoProxyCreator类的getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource)方法

@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

   List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
   if (advisors.isEmpty()) {

     return DO_NOT_PROXY;
   }

   return advisors.toArray();
}
1
2
3
4
5
6
7
8
9
10
11
12

AbstractAdvisorAutoProxyCreator类的getAdvicesAndAdvisorsForBean()方法的主要作用是获取需要AOP增强的方法,本质上是调用的findEligibleAdvisors()方法获取需要AOP增强的方法,返回List集合后,调用toArray()方法返回数组。

(2)解析AbstractAdvisorAutoProxyCreator类的indEligibleAdvisors(Class<?> beanClass, String beanName)方法

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
   List<Advisor> candidateAdvisors = findCandidateAdvisors();
   List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);

   extendAdvisors(eligibleAdvisors);

   if (!eligibleAdvisors.isEmpty()) {

     eligibleAdvisors = sortAdvisors(eligibleAdvisors);
   }
   return eligibleAdvisors;
}
1
2
3
4
5
6
7
8
9
10
11
12

在AbstractAdvisorAutoProxyCreator类的indEligibleAdvisors()方法中,首先调用findCandidateAdvisors()方法获取到切面类中所有的切面方法,并封装成List集合candidateAdvisors,并将其传递到findAdvisorsThatCanApply()方法中处理切面。

(3)解析AbstractAdvisorAutoProxyCreator类的findAdvisorsThatCanApply(List candidateAdvisors, Class<?> beanClass, String beanName)方法

protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
   ProxyCreationContext.setCurrentProxiedBeanName(beanName);
   try {
     return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
   }
   finally {
     ProxyCreationContext.setCurrentProxiedBeanName(null);
   }
}
1
2
3
4
5
6
7
8
9

AbstractAdvisorAutoProxyCreator类的findAdvisorsThatCanApply()方法中,首先记录当前线程要代理的Bean的名称,然后调用AopUtils类的findAdvisorsThatCanApply()方法处理切面,最后移除当前线程要代理的Bean的名称。

(4)解析AopUtils类的findAdvisorsThatCanApply(List candidateAdvisors, Class<?> clazz)方法

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {

   /*************省略其他代码*************/

   for (Advisor candidate : candidateAdvisors) {
     if (candidate instanceof IntroductionAdvisor) {
       // already processed 
       continue; 
     } 
     if (canApply(candidate, clazz, hasIntroductions)) {
       eligibleAdvisors.add(candidate);
     }
   }
   return eligibleAdvisors;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在AopUtils类的findAdvisorsThatCanApply()方法中,会遍历传递进来的candidateAdvisors集合,处理每个遍历出的candidate元素,如果candidate是IntroductionAdvisor类型,说明已经处理过,跳过本次循环。否则,调用canApply()方法进行处理。

(5)解析AopUtils类的canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions)方法

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {

    if (advisor instanceof IntroductionAdvisor) {
        return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
    }
    else if (advisor instanceof PointcutAdvisor pca) {
        return canApply(pca.getPointcut(), targetClass, hasIntroductions);
    }
    else {
        // It doesn't have a pointcut so we assume it applies.
        return true;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

在AopUtils类的canApply()方法中,调用了另一个重载的canApply()方法。

(6)解析AopUtils类的canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions)方法

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {

    Assert.notNull(pc, "Pointcut must not be null");
    
    if (!pc.getClassFilter().matches(targetClass)) {
        return false; 
    }
    /*************省略其他代码***********/
    return false;
}
1
2
3
4
5
6
7
8
9
10

在AopUtils类的canApply()方法中,首先会调用pc对象的getClassFilter()获取Class过滤器对象,再调用Class过滤器对象的matches()方法判断是否匹配规则,如果不匹配规则就返回false。

(7)解析AspectJExpressionPointcut类的getClassFilter()方法

@Override
public ClassFilter getClassFilter() {
   obtainPointcutExpression();
   return this;
}
1
2
3
4
5

在AspectJExpressionPointcut类的getClassFilter()方法中,调用了obtainPointcutExpression()方法。

(8)解析AspectJExpressionPointcut类的obtainPointcutExpression()方法

private PointcutExpression obtainPointcutExpression() {
    if (getExpression() == null) {
        throw new IllegalStateException("Must set property 'expression' before attempting to match");
    }
    if (this.pointcutExpression == null) {
        this.pointcutClassLoader = determinePointcutClassLoader();
        this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader);
    }
    return this.pointcutExpression;
}
1
2
3
4
5
6
7
8
9
10

在AspectJExpressionPointcut类的obtainPointcutExpression()方法中,如果pointcutExpression为空,则调用determinePointcutClassLoader()方法获取加载切入点表达式的类加载器,随后调用buildPointcutExpression()方法获取切入点表达式对象,赋值给pointcutExpression,最后返回pointcutExpression对象。此时,就将切入点表达式封装到PointcutExpression对象中,并存储到了AspectJExpressionPointcut类的pointcutExpression成员变量中。

(9)解析AspectJExpressionPointcut类的buildPointcutExpression(@Nullable ClassLoader classLoader)方法

private PointcutExpression buildPointcutExpression(@Nullable ClassLoader classLoader) {
    PointcutParser parser = initializePointcutParser(classLoader);
    PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length];
    
    for (int i = 0; i < pointcutParameters.length; i++) {
        pointcutParameters[i] = parser.createPointcutParameter(this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);
    }
    
    return parser.parsePointcutExpression(replaceBooleanOperators(resolveExpression()), this.pointcutDeclarationScope, pointcutParameters);
}
1
2
3
4
5
6
7
8
9
10

在AspectJExpressionPointcut类的buildPointcutExpression()方法中,会调用parser对象的parsePointcutExpression()方法解析切入点表达式。

(10)解析PointcutParser类的parsePointcutExpression(String expression, Class<?> inScope, PointcutParameter[] formalParameters)方法

public PointcutExpression parsePointcutExpression(String expression, Class<?> inScope, PointcutParameter[] formalParameters) throws UnsupportedPointcutPrimitiveException, IllegalArgumentException {
    PointcutExpressionImpl pcExpr = null;
    try {
        Pointcut pc = resolvePointcutExpression(expression, inScope, formalParameters);
       /*********省略其他代码*********/
    return pcExpr;
}
1
2
3
4
5
6
7

在PointcutParser类的parsePointcutExpression()方法中,会调用resolvePointcutExpression()方法处理切入点表达式的逻辑。

(11)解析PointcutParser类的resolvePointcutExpression(String expression, Class<?> inScope, PointcutParameter[] formalParameters)方法

protected Pointcut resolvePointcutExpression(String expression, Class<?> inScope, PointcutParameter[] formalParameters) {
    try {
    
        /************省略其他代码************/
        IScope resolutionScope = buildResolutionScope((inScope == null ? Object.class : inScope), formalParameters);
        pc = pc.resolve(resolutionScope);
        return pc;
    } catch (ParserException pEx) {
        throw new IllegalArgumentException(buildUserMessageFromParserException(expression, pEx));
    }
}
1
2
3
4
5
6
7
8
9
10
11

在PointcutParser类的resolvePointcutExpression()方法中,会调用pc对象的resolve()方法处理切入点表达式。

(12)解析Pointcut类的resolve(IScope scope)方法

public final Pointcut resolve(IScope scope) {

    /*********省略代码*********/
    this.resolveBindings(bindingResolutionScope, bindingTable);
    bindingTable.checkAllBound(bindingResolutionScope);
    
    this.state = RESOLVED;
    return this;
}
1
2
3
4
5
6
7
8
9

在Pointcut类的resolve()方法中,会调用resolveBindings()方法来处理绑定关系。

(13)解析ReferencePointcut类的resolveBindings(IScope scope, Bindings bindings)方法

public void resolveBindings(IScope scope, Bindings bindings) {

    /************省略其他代码************/
    
    ResolvedPointcutDefinition pointcutDef = searchType.findPointcut(name);
    
    // if we're not a static reference, then do a lookup of outers    
    if (pointcutDef == null && onType == null) {
    
        while (true) {
            UnresolvedType declaringType = searchType.getDeclaringType();
    
            if (declaringType == null) {
                break;
            }
    
            searchType = declaringType.resolve(scope.getWorld());
            pointcutDef = searchType.findPointcut(name);
    
            if (pointcutDef != null) {
                // make this a static reference
                onType = searchType;
                break;
            }
        }
    }
    /************省略其他代码************/
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

在ReferencePointcut类的resolveBindings()方法中会调用searchType对象的findPointcut()方法,查找切入点表达式。

(14)解析ResolvedType类的findPointcut(String name)方法

public ResolvedPointcutDefinition findPointcut(String name) {
    for (Iterator<ResolvedMember> i = getPointcuts(); i.hasNext();) {
         /***********省略其他代码***********/
    }
    /***********省略其他代码***********/
    return null; // should we throw an exception here?
}
1
2
3
4
5
6
7

在ResolvedType类的findPointcut()方法的for循环条件中,会调用hasNext()方法来遍历调用getPointcuts()方法获取到的切入点表达式的迭代器。

(15)解析Iterators类的mapOver(final Iterator a, final Getter<A, B> g)方法

public static <A, B> Iterator<B> mapOver(final Iterator<A> a, final Getter<A, B> g) {

    return new Iterator<B>() {    
        Iterator<B> delegate = new Iterator<B>() {
            public boolean hasNext() {
                if (!a.hasNext()) {
                    return false;
                }
                A o = a.next();
                delegate = append1(g.get(o), this);
                return delegate.hasNext();
            }
            public B next() {
                if (!hasNext()) {
                    throw new UnsupportedOperationException();
                }
                return delegate.next();
            }
            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
        public boolean hasNext() {
            return delegate.hasNext();
        }
        public B next() {
            return delegate.next();
        }
        public void remove() {
            throw new UnsupportedOperationException();
        }
    };
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

在Iterators类的mapOver()方法中的hasNext()方法时,就会调用delegate的hasNext()方法。也就是会调用创建delegate对象时的hasNext()方法。此时,就会调用传递到mapOver()方法中的g参数的get()方法。

(16)解析PointcutGetter类的get(ResolvedType o)方法

private static class PointcutGetter implements Iterators.Getter<ResolvedType, ResolvedMember> {
    @Override
    public Iterator<ResolvedMember> get(ResolvedType o) {
        return Iterators.array(o.getDeclaredPointcuts());
    }
}
1
2
3
4
5
6

在PointcutGetter类的get()方法中,首先会调用o对象的getDeclaredPointcuts()方法获取声明的切入点表达式,随后调用Iterators类的array()方法将其转化成Iterator迭代器并返回。

(17)解析ReferenceType类的getDeclaredPointcuts()方法

@Override
public ResolvedMember[] getDeclaredPointcuts() {
    if (parameterizedPointcuts != null) {
        return parameterizedPointcuts;
    }
    if (isParameterizedType()) {
        ResolvedMember[] delegatePointcuts = getDelegate()
            .getDeclaredPointcuts();
        parameterizedPointcuts = new ResolvedMember[delegatePointcuts.length];
        for (int i = 0; i < delegatePointcuts.length; i++) {
            parameterizedPointcuts[i] = delegatePointcuts[i]
                .parameterizedWith(getTypesForMemberParameterization(),
                                   this, isParameterizedType());
        }
    
        return parameterizedPointcuts;
    } else {
        return getDelegate().getDeclaredPointcuts();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

在ReferenceType类的getDeclaredPointcuts()方法中,会首先调用getDelegate()方法获取代理对象,随后调用代理对象的getDeclaredPointcuts()方法获取声明的切入点表达式。

(18)解析Java15ReflectionBasedReferenceTypeDelegate类的getDeclaredPointcuts()方法

@Override
public ResolvedMember[] getDeclaredPointcuts() {
    if (pointcuts == null) {
   
        Pointcut[] pcs = this.myType.getDeclaredPointcuts();
    
        pointcuts = new ResolvedMember[pcs.length];
    
        InternalUseOnlyPointcutParser parser = null;
    
        World world = getWorld();
    
        if (world instanceof ReflectionWorld) {
    
            parser = new InternalUseOnlyPointcutParser(classLoaderReference.getClassLoader(), (ReflectionWorld) getWorld());
    
        } else {
            parser = new InternalUseOnlyPointcutParser(classLoaderReference.getClassLoader());
        }
    
        Set<PointcutDesignatorHandler> additionalPointcutHandlers = world.getRegisteredPointcutHandlers();
        for (PointcutDesignatorHandler handler : additionalPointcutHandlers) {
    
            parser.registerPointcutDesignatorHandler(handler);
        }
        //步骤一
        for (int i = 0; i < pcs.length; i++) {
            AjType<?>[] ptypes = pcs[i].getParameterTypes();
            UnresolvedType[] weaverPTypes = new UnresolvedType[ptypes.length];
            for (int j = 0; j < weaverPTypes.length; j++) {
                weaverPTypes[j] = this.typeConverter.fromType(ptypes[j].getJavaClass());
            }
            pointcuts[i] = new DeferredResolvedPointcutDefinition(getResolvedTypeX(), pcs[i].getModifiers(), pcs[i].getName(),weaverPTypes);
        }
        //步骤二
        PointcutParameter[][] parameters = new PointcutParameter[pcs.length][];
        for (int i = 0; i < pcs.length; i++) {
            AjType<?>[] ptypes = pcs[i].getParameterTypes();
    
            String[] pnames = pcs[i].getParameterNames();
    
            if (pnames.length != ptypes.length) {
    
                pnames = tryToDiscoverParameterNames(pcs[i]);
    
                if (pnames == null || (pnames.length != ptypes.length)) { 
                    /**********省略其他代码*********/
                }
            }
            parameters[i] = new PointcutParameter[ptypes.length];
            for (int j = 0; j < parameters[i].length; j++) {
    
                parameters[i][j] = parser.createPointcutParameter(pnames[j], ptypes[j].getJavaClass());
    
            }
    
            String pcExpr = pcs[i].getPointcutExpression().toString();
    
            org.aspectj.weaver.patterns.Pointcut pc = parser.resolvePointcutExpression(pcExpr, getBaseClass(), parameters[i]);
    
            ((ResolvedPointcutDefinition) pointcuts[i]).setParameterNames(pnames);
    
            ((ResolvedPointcutDefinition) pointcuts[i]).setPointcut(pc);
    
        }
    
        //步骤三
    
        for (int i = 0; i < pointcuts.length; i++) {
    
            ResolvedPointcutDefinition rpd = (ResolvedPointcutDefinition) pointcuts[i];
    
            rpd.setPointcut(parser.concretizePointcutExpression(rpd.getPointcut(), getBaseClass(), parameters[i]));
    
        }
    
    }
    
    return pointcuts;

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

上述代码核心逻辑大体上可以分成三步:

  1. 获取声明的切入点表达式,将其封装发到pointcuts数组中。
  2. 循环pointcuts数组中的切入点表达式,将数组中的元素强制为ResolvedPointcutDefinition类型后,设置参数名称和切入点。
  3. 具象化切入点表达式。

同时,Java15ReflectionBasedReferenceTypeDelegate类的getDeclaredPointcuts()方法的开始部分调用了myType对象的getDeclaredPointcuts()方法获取声明的切入点。

(19)解析AjTypeImpl类的getDeclaredPointcuts()方法

public Pointcut[] getDeclaredPointcuts() {

    if (declaredPointcuts != null) return declaredPointcuts;
    
    List<Pointcut> pointcuts = new ArrayList<>();
    
    Method[] methods = clazz.getDeclaredMethods();
    
    for (Method method : methods) {
    
        Pointcut pc = asPointcut(method);
    
        if (pc != null) pointcuts.add(pc);
    
    }
    
    Pointcut[] ret = new Pointcut[pointcuts.size()];
    
    pointcuts.toArray(ret);
    
    declaredPointcuts = ret;
    
    return ret;

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

在AjTypeImpl类的getDeclaredPointcuts()方法中,会获取切面类中声明的所有方法,遍历所有的方法,调用asPointcut()方法将其封装成Pointcut类型的切入点对象,如果对象不为空,就存入pointcuts集合中,并最终将pointcuts集合转化成数组,赋值给成员变量declaredPointcuts后再直接返回。

(20)解析AjTypeImpl类的asPointcut(Method method)方法

private Pointcut asPointcut(Method method) {

    org.aspectj.lang.annotation.Pointcut pcAnn = method.getAnnotation(org.aspectj.lang.annotation.Pointcut.class);
    if (pcAnn != null) {
        String name = method.getName();
        if (name.startsWith(ajcMagic)) {
    
            // extract real name
    
            int nameStart = name.indexOf("$$");
    
            name = name.substring(nameStart +2,name.length());
    
            int nextDollar = name.indexOf("$");
    
            if (nextDollar != -1) name = name.substring(0,nextDollar);
        }
        return new PointcutImpl(name,pcAnn.value(),method,AjTypeSystem.getAjType(method.getDeclaringClass()),pcAnn.argNames());
    
    } else {
        return null;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

在AjTypeImpl类的asPointcut()方法中,会解析方法上的@Pointcut注解,如果注解为空,则直接返回null。否则,解析方法的元数据信息,传入PointcutImpl类的构造方法生成PointcutImpl对象并返回。也就是说,最终会将切入点信息封装成PointcutImpl对象并返回。最终会将解析出的切入点表达式存储到了AspectJExpressionPointcut类的pointcutExpression成员变量中。

帮助我们改善此页面! (opens new window)
上次更新: 2024/08/30, 01:19:49
Spring源码解析
SpringCloud Alibaba核心知识

← Spring源码解析 SpringCloud Alibaba核心知识→

最近更新
01
SpringCloud Alibaba实战
08-22
02
SpringCloud Alibaba核心知识
08-22
03
两数之和
08-08
更多文章>
Theme by Vdoing | Copyright © 2023-2024 BlazeMaple
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式