>Java >java지도 시간 >Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석

WBOY
WBOY앞으로
2022-10-06 09:00:271281검색

이 기사는 Spring이 생성하는 Bean의 생명주기와 관련된 문제를 주로 소개하는 java에 대한 관련 지식을 제공합니다. 모두에게 도움이 되기를 바랍니다.

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석

추천 학습: "java 비디오 튜토리얼"

1.Bean 생성 라이프 사이클

UserService.class —> 인수 없는 생성자(추론 생성자) —> 일반 객체 —> 종속성 주입(값 할당) ​​@Autowired를 사용하여 속성에) —> 초기화 전(@PostConstruct를 사용하여 메서드 실행) —> 초기화( <code>afterPropertiesSet 초기화 후(<code>AOP 관련 로직 실행) —> 프록시 객체 —> Bean@Autowired的属性赋值) —> 初始化前(执行带有@PostConstruct的方法) —> 初始化(执行实现了InitializingBean接口的afterPropertiesSet方法) —> 初始化后(执行AOP相关逻辑) —> 代理对象 —> Bean

类似于:男孩 —> 依赖注入 —> 男人

大致过程如下:

  • 利用该类的构造方法来实例化得到一个对象(但是如何一个类中有多个构造方法,Spring 则会进行选择,这个叫做推断构造方法
  • 得到一个对象后,Spring 会判断该对象中是否存在被@Autowired注解了的属性,把这些属性找出来并由 Spring 进行赋值(依赖注入
  • 依赖注入后,Spring 会判断该对象是否实现了 BeanNameAware 接口、BeanClassLoaderAware接口、BeanFactoryAware 接口,如果实现了,就表示当前对象必须实现该接口中所定义的 setBeanName()setBeanClassLoader()setBeanFactory()方法,那么 Spring 就会调用这些方法并传入相应的参数(Aware回调
  • Aware 回调后,Spring 会判断该对象中是否存在某个方法被@PostConstruct注解了,如果存在,Spring 会调用当前对象的此方法(初始化前
  • 紧接着,Spring 会判断该对象是否实现了InitializingBean接口,如果实现了,就表示当前对象必须实现该接口中的afterPropertiesSet()方法,那么 Spring 就会调用当前对象中的afterPropertiesSet()方法(初始化
  • 最后,Spring 会判断当前对象需不需要进行 AOP,如果不需要那么Bean就创建完了,如果需要进行AOP,则会进行动态代理并生成一个代理对象作为Bean(初始化后

当Spring根据UserService类来创建一个Bean时:

  • 如果不用进行AOP,那么Bean就是UserService类的构造方法所得到的对象。
  • 如果需要进行AOP,那么Bean就是UserService的代理类所实例化得到的对象,而不是UserService本身所得到的对象。

Bean对象创建出来后:

  • 如果当前Bean是单例Bean,那么会把该Bean对象存入一个Map<string object></string>,Map的key为beanName,value为Bean对象。这样下次getBean时就可以直接从Map中拿到对应的Bean对象了。(实际上,在Spring源码中,这个Map就是单例池
  • 如果当前Bean是原型Bean,那么后续没有其他动作,不会存入一个Map,下次getBean时会再次执行上述创建过程,得到一个新的Bean对象。

推断构造方法:

  • 如果一个类里面有无参的构造方法,那么Spring默认就会用这个无参的构造方法。
  • 如果一个类里面只有一个有参的构造方法,那么Spring就会用这个有参的构造方法。
  • 如果一个类里面有多个有参的构造方法,并且没有无参的构造方法,那么Spring会报错。
  • 如果想要指定Spring用哪个构造方法,可以在该构造方法上加@Autowired

@Bean会覆盖@Compoment

은 다음과 유사합니다: Boy—> 주입 —> Man

일반적인 프로세스는 다음과 같습니다.

  • 클래스의 생성자를 사용하여 객체를 인스턴스화합니다(그러나 클래스를 얻는 방법은 여러 가지가 있습니다). 이를 유추 생성자 메서드라고 합니다.
  • 객체를 가져온 후 Spring은 개체에 @Autowired가 있는지 확인합니다. object >주석이 달린 속성, 이러한 속성을 찾아서 Spring에 의해 할당(Dependency 주입🎜)
  • 의존성 주입 후 Spring은 객체가 BeanNameAware 인터페이스를 구현하는지 여부를 결정합니다. BeanClassLoaderAware 인터페이스, BeanFactoryAware 인터페이스가 구현된 경우 이는 현재 객체가 인터페이스 >setBeanClassLoader에 정의된 setBeanName(), 를 구현해야 함을 의미합니다. (), setBeanFactory() 메소드를 사용하면 Spring은 이러한 메소드를 호출하고 해당 매개변수(🎜Aware 콜백🎜)를 전달합니다.
  • Aware 콜백 후 Spring은 객체에 @PostConstruct라는 주석이 달린 메소드가 있는지 확인합니다. 존재하는 경우 Spring은 현재 객체의 이 메소드를 호출합니다(🎜초기화 전🎜)
  • Close 그런 다음 Spring은 객체가 InitializingBean 인터페이스를 구현하는지 여부를 결정합니다. 그렇다면 이는 현재 객체가 인터페이스에서 afterPropertiesSet() 메소드를 구현해야 함을 의미합니다. 그런 다음 Spring은 호출합니다. 현재 객체의 afterPropertiesSet() 메서드(🎜initialization🎜)
  • 마지막으로 Spring은 현재 객체가 AOP인지 여부를 결정합니다. not 필요한 경우 Bean이 생성됩니다. AOP가 필요한 경우 동적 프록시가 수행되고 프록시 객체가 Bean으로 생성됩니다. (🎜초기화 후🎜)
🎜🎜Spring이 Bean을 생성할 때 UserService 클래스 기반 :🎜🎜
  • AOP가 필요하지 않은 경우 Bean은 UserService 클래스의 생성자 메서드에서 얻은 개체입니다.
  • AOP가 필요한 경우 Bean은 UserService 자체에서 얻은 객체가 아니라 UserService 프록시 클래스에 의해 인스턴스화된 객체입니다.
🎜🎜Bean 객체가 생성된 후: 🎜🎜
  • 현재 Bean이 🎜Single Bean🎜인 경우 Bean 객체는 Map, Map의 키는 beanName이고 값은 Bean 개체입니다. 이런 방식으로 다음에 Bean을 얻을 때 해당 Bean 객체를 Map에서 직접 얻을 수 있습니다. (실제로 Spring 소스 코드에서 이 Map은 🎜Single Case Pool🎜입니다.)
  • 현재 Bean이 프로토타입 Bean이면 다른 후속 조치가 없으며 Map이 저장되지 않습니다. 다음에 getBean을 실행하면 새로운 Bean 객체를 얻기 위해 위의 생성 과정을 다시 실행합니다.
🎜🎜추론된 생성자: 🎜🎜
  • 클래스에 매개변수 없는 생성자가 있는 경우 Spring은 기본적으로 이 매개변수 없는 생성자를 사용합니다.
  • 클래스에 매개변수화된 생성자가 하나만 있는 경우 Spring은 이 매개변수화된 생성자를 사용합니다.
  • 클래스에 매개변수화된 생성자가 여러 개 있고 매개변수 없는 생성자가 없으면 Spring은 오류를 보고합니다.
  • Spring이 사용하는 생성자를 지정하려면 생성자에 @Autowired를 추가하면 됩니다.
🎜@Bean@Compoment🎜🎜🎜를 재정의합니다. 참고: 🎜🎜🎜Spring이 매개변수화된 생성자를 선택하면 Spring은 이를 매개변수화된 생성자를 호출할 때 생성자의 경우 매개변수를 전달해야 합니다. 그러면 이러한 매개변수는 어디서 오는 걸까요? 🎜🎜🎜Spring은 입력 매개변수의 유형과 이름을 기반으로 Spring 컨테이너에서 Bean 객체를 찾습니다(싱글톤 Bean을 예로 들면 Spring은 싱글톤 풀의 Map에서 이를 찾습니다). 🎜🎜
  • 첫 번째 검색은 입력 매개변수 유형을 기준으로 하나만 검색되면 입력 매개변수로 직접 사용합니다.
  • 유형을 기준으로 여러 개가 검색되면 입력 매개변수 이름을 기준으로 하나만 결정합니다.
  • 만약 결국 발견되지 않으면 오류가 보고되고, 현재 Bean 객체를 생성할 수 없습니다.

어떤 생성 방법을 사용할지 결정하고, 매개변수를 취하는 Bean 객체를 결정하는 과정을 구성 방법 유추라고 합니다. .

2. Spring AOP

AOP의 일반적인 프로세스는 Bean을 생성하는 과정에서 마지막 단계에서 Spring이 현재 생성 중인 Bean에 AOP가 필요한지 여부를 판단하고 필요한 경우 이를 수행하는 것입니다. 동적 프록시가 됩니다.

현재 Bean 객체에 AOP 작업이 필요한지 확인하는 방법:

먼저 Spring 컨테이너에서 모든 측면 Bean을 찾습니다.
  • 각 측면 Bean을 순회한 후 각 측면 Bean의 각 메소드를 순회하여 @Before@After와 같은 주석이 작성되었는지 확인합니다.
  • 작성되면 해당 메소드에 해당하는 Pointcut이 현재 Bean 객체의 클래스와 일치하는지 판단합니다. @Before@After 等注解。
  • 如果写了,则判断该方法所对应的Pointcut是否和当前Bean对象的类相匹配
  • 如果匹配,则表示当前Bean对象是需要进行 AOP 操作的。

上面第三步找到匹配的之后,会将匹配的所有方法缓存起来,后面在执行切面方法的时候,可以快速从缓存中拿出来,提高执行效率。

利用cglib进行AOP的大致流程:

  • 生成代理类UserServiceProxy,代理类继承UserService
  • 代理类中重写了父类的方法,比如UserService中的test()方法代理类中还会有一个target属性,该属性的值为被代理的对象(也就是通过UserService类推断构造方法实例化出来的对象,进行了依赖注入、初始化等步骤的对象)
  • 代理类中的test()方法被执行时的逻辑如下:
    • 执行切面逻辑(@Before)
    • 调用target.test()

当我们从Spring容器得到UserService的Bean对象时,拿到的就是UserServiceProxy所生成的对象,也就是代理对象。

调用UserService代理对象.test( ) —> 执行切面逻辑 —> target.test( ),注意target对象不是代理对象,而是被代理的对象。

UserServiceProxy(代理类) ---> 代理对象 ---> 代理对象.target = 普通对象
代理对象.test();

class UserServiceProxy extends UserService {
  
  UserService target;
  
  public void test() {
    // 执行切面逻辑 @Before --> 从匹配的切面方法的缓存中拿出来
    
    target.test(); // 调用普通对象的test方法
    
  }
  
}

3.Spring 事务

当我们在某个方法上加了@Transactional注解后,就表示该方法在调用时会开启Spring事务,而这个方法所在的类所对应的Bean对象会是该类的代理对象

Spring事务的代理对象执行某个方法时的步骤:

  • 判断当前执行的方法是否存在@Transactional注解
  • 如果存在,则利用事务管理器(TransactionMananger)创建一个数据库连接
  • 修改数据库连接的 autocommit 为 false
  • 执行 target.test(),执行程序员所写的业务逻辑代码,也就是执行 sql
  • 执行完了之后如果没有出现异常,则提交,否则回滚

Spring事务是否会失效的判断标准:某个加了@Transactional注解的方法被调用时,要判断到底是不是直接被代理对象调用的,如果是则事务会生效,如果不是则会失效。

UserServiceProxy(代理类) ---> 代理对象 ---> 代理对象.target = 普通对象
代理对象.test();

class UserServiceProxy extends UserService {
  
  UserService target;
  
  public void test() {
    // 1.先看看方法上面有没有加@Transactional
    // 2.通过事务管理器dataSource,创建一个数据库连接conn
    // 3.设置conn.autocommit = false,表示不自动提交事务
    
    target.test(); // 调用普通对象的test方法
    
    conn.commit(); // 如果方法都执行成功,那就手动提交事务
    conn.rollback(); // 如果某个方法执行失败,那就会回滚事务
    
  }
  
}

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석

4.Spring 源码阅读前戏

BeanDefinition

BeanDefinition表示Bean定义,BeanDefinition中存在很多属性用来描述一个Bean的特点。

比如:

  • class,表示Bean类型
  • scope,表示Bean的作用域,单例或原型等
  • lazyInit:表示Bean是否是懒加载
  • initMethodName:表示Bean初始化时要执行的方法
  • destroyMethodName:表示Bean销毁时要执行的方法还有很多…

声明式定义 Bean:

可以通过以下几种方式来定义Bean:

  • <bean></bean>
  • @Bean
  • @Component(@Service、@Controller)

也可以通过编程式定义 Bean

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

// 生成一个BeanDefinition对象,并设置beanClass为User.class,并注册到ApplicationContext中
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(User.class);
context.registerBeanDefinition("user", beanDefinition);

System.out.println(context.getBean("user"));

还可以通过BeanDefinition设置一个Bean的其他属性

beanDefinition.setScope("prototype"); // 设置作用域
beanDefinition.setInitMethodName("init"); // 设置初始化方法
beanDefinition.setLazyInit(true); // 设置懒加载

声明式定义和编程式定义的Bean,最终都会被Spring解析为对应的BeanDefinition对象,并放入Spring容器中。

BeanDefinitionReader

接下来介绍几种在Spring源码中常见的BeanDefinition读取器(BeanDefinitionReader

AnnotatedBeanDefinitionReader

可以直接把某个类转换为BeanDefinition일치하면 현재 Bean 객체가 AOP 작업을 수행해야 함을 의미합니다.

🎜위의 세 번째 단계에서 일치하는 항목을 찾은 후 일치하는 모든 메서드가 나중에 캐시에서 실행될 때 캐시에서 빠르게 제거되어 실행 효율성을 높일 수 있습니다. 🎜
🎜AOP를 수행하기 위해 cglib를 사용하는 일반적인 프로세스: 🎜
🎜🎜UserService를 상속하는 프록시 클래스 UserServiceProxy를 생성합니다.🎜🎜부모 클래스의 메서드는 다음에서 재정의됩니다. UserService의 test() 메소드와 같은 프록시 클래스에는 프록시 클래스의 대상 속성도 있습니다. 이 속성의 값은 프록시되는 개체(즉, 추론된 개체를 통해 인스턴스화되는 개체)입니다. UserService 클래스의 생성 메소드. 종속성 주입, 초기화 등을 위한 객체 단계)🎜🎜프록시 클래스의 test() 메소드가 실행될 때🎜로직은 다음과 같습니다. 🎜🎜🎜실행 Aspect logic (@Before)🎜🎜Call target.test()🎜🎜🎜🎜🎜Spring 컨테이너에서 UserService의 Bean 객체를 얻을 때 우리가 얻는 것은 UserServiceProxy에 의해 생성된 객체입니다. 프록시 객체입니다. 🎜🎜UserService 프록시 object.test() 호출 —> 애스펙트 로직 실행 —> target.test(). 대상 개체는 프록시 개체가 아니라 프록시된 개체입니다. 🎜
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(context);

// 将User.class解析为BeanDefinition
annotatedBeanDefinitionReader.register(User.class);

System.out.println(context.getBean("user"));
🎜3.Spring transaction🎜🎜 메소드에 @Transactional 주석을 추가하면 해당 메소드가 호출될 때 Spring 트랜잭션을 시작한다는 의미이며, 이 메소드가 포함된 클래스는 해당 Bean 개체는 클래스의 🎜프록시 개체🎜가 됩니다. 🎜🎜🎜Spring 트랜잭션의 프록시 객체가 메소드를 실행하는 단계: 🎜🎜🎜🎜현재 실행된 메소드에 @Transactional 주석이 있는지 확인합니다. 🎜🎜존재하는 경우 트랜잭션 관리자(TransactionMananger)를 사용합니다. ) 데이터베이스 연결 만들기🎜🎜데이터베이스 연결의 autocommit를 false로 수정🎜🎜 target.test()를 실행하여 프로그래머가 작성한 비즈니스 로직 코드를 실행합니다. 은, sql 실행 🎜🎜실행 후 예외가 발생하지 않으면 제출, 그렇지 않으면 롤백🎜🎜🎜Spring 트랜잭션 실패 여부 판단 기준: 🎜@Transactional이라는 주석이 붙은 메서드 호출 시 직접 여부를 확인해야 함 프록시 객체에 의해 호출되면 트랜잭션이 적용되고, 그렇지 않으면 실패합니다. 🎜🎜
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(context);
        int i = xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");

        System.out.println(context.getBean("user"));

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석🎜🎜4. foreplay🎜

BeanDefinition

🎜BeanDefinition을 읽는 스프링 소스 코드는 Bean 정의를 나타냅니다. BeanDefinition에는 Bean의 특성을 설명하는 많은 속성이 있습니다. 🎜🎜🎜예: 🎜🎜🎜🎜🎜class🎜, Bean 유형을 나타냄 🎜🎜🎜scope🎜, Bean의 범위, 싱글톤 또는 프로토타입 등을 나타냄 🎜🎜🎜lazyInit🎜: Bean이 지연 로드되었는지 여부를 나타냄 🎜🎜🎜initMethodName 🎜 : Bean이 초기화될 때 실행될 메소드를 나타냅니다.🎜🎜🎜destroyMethodName🎜: Bean이 파괴될 때 실행될 메소드가 많다는 것을 나타냅니다...🎜🎜🎜🎜선언적으로 정의된 Bean:🎜🎜 🎜🎜Bean은 다음과 같은 방법으로 정의할 수 있습니다. 🎜🎜🎜🎜<bean></bean>🎜🎜@Bean🎜🎜@Component (@Service, @Controller)🎜🎜
🎜Beans 프로그래밍 방식으로 정의할 수도 있습니다🎜
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.refresh();

        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
        scanner.scan("cn.xx");

        System.out.println(context.getBean("user"));
🎜BeanDefinition을 통해 Bean의 다른 속성을 설정할 수도 있습니다🎜
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
  MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
            ...
}
🎜선언적 및 프로그래밍 방식으로 정의된 Bean은 결국 Spring에 의해 해당 BeanDefinition 개체로 구문 분석되어 Spring 컨테이너에 배치됩니다. 🎜

BeanDefinitionReader

🎜다음은 Spring 소스 코드의 몇 가지 일반적인 BeanDefinition 리더(BeanDefinitionReader)를 소개합니다. 🎜

AnnotatedBeanDefinitionReader

🎜특정 클래스를 직접 변환할 수 있습니다. BeanDefinition으로 변환되고 클래스의 주석이 구문 분석됩니다. 🎜예: 🎜🎜
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(context);

// 将User.class解析为BeanDefinition
annotatedBeanDefinitionReader.register(User.class);

System.out.println(context.getBean("user"));

它能解析的注解有:@Conditional,@Scope、@Lazy、@Primary、@DependsOn、@Role、@Description

XmlBeanDefinitionReader

可以解析<bean></bean>标签

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(context);
        int i = xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");

        System.out.println(context.getBean("user"));

ClassPathBeanDefinitionScanner

ClassPathBeanDefinitionScanner是扫描器,它的作用和BeanDefinitionReader类似,可以进行扫描,扫描某个包路径,对扫描到的类进行解析,比如,扫描到的类上如果存在 @Component 注解,那么就会把这个类解析成为一个BeanDefinition

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.refresh();

        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
        scanner.scan("cn.xx");

        System.out.println(context.getBean("user"));

BeanFactory

BeanFactory表示Bean工厂,所以很明显,BeanFactory会负责创建Bean,并且提供获取Bean的API。

而ApplicationContext是BeanFactory的一种,在Spring源码中,是这么定义的:

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
  MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
            ...
}

首先,在Java中,接口是可以多继承的,我们发现ApplicationContext继承了ListableBeanFactoryHierarchicalBeanFactory,而 ListableBeanFactory 和HierarchicalBeanFactory 都继承至 BeanFactory,所以我们可以认为 ApplicationContext 继承了BeanFactory,相当于苹果继承水果,宝马继承汽车一样,ApplicationContext 也是 BeanFactory 的一种,拥有 BeanFactory 支持的所有功能,不过 ApplicationContext 比 BeanFactory 更加强大,ApplicationContext 还继承了其他接口,也就表示 ApplicationContext 还拥有其他功能,比如MessageSource 表示国际化,ApplicationEventPublisher 表示事件发布,EnvironmentCapable 表示获取环境变量等等,关于 ApplicationContext 后面再详细讨论。

在Spring的源码中,当我们new一个ApplicationContext时,其底层会new一个BeanFactory,当使用ApplicationContext的某些方法时,比如getBean(),底层调用的就是BeanFactory的getBean()方法。

在Spring源码中,BeanFactory接口存在一个非常重要的实现类是:DefaultListableBeanFactory,也是非常核心的。

所以,我们可以直接使用DefaultListableBeanFactory,而不需要使用 ApplicationContext 的某个实现类,比如:

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        beanDefinition.setBeanClass(User.class);
        beanFactory.registerBeanDefinition("user", beanDefinition);
        System.out.println(beanFactory.getBean("user"));

DefaultListableBeanFactory是非常强大的,支持很多功能,可以通过查看DefaultListableBeanFactory 的类继承结构图:

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석

  • AliasRegistry: 별칭 기능 지원, 하나의 이름이 여러 개의 별칭에 해당할 수 있음
  • BeanDefinitionRegistry: 특정
  • BeanDefinitionBeanFactory: Bean 팩토리를 기반으로 할 수 있음 Bean 객체를 얻기 위한 bean의 이름, 유형 또는 별칭
  • SingletonBeanRegistry: 단일 인스턴스Bean
  • SimpleAliasRegistry:에 정의된 함수를 구현하는 클래스입니다. AliasRegistry 인터페이스. 별칭 함수 지원
  • ListableBeanFactory: BeanFactory를 기반으로 다른 함수가 추가됩니다. 모든 BeanDefinitions의 beanNames를 얻을 수 있으며, 특정 유형을 기반으로 해당 beanNames를 얻을 수 있습니다. 특정 Type을 기반으로 해당 Bean} 매핑 관계
  • HierarchicalBeanFactory: BeanFactory를 기반으로 상위 BeanFactory를 획득하는 기능이 추가됨
  • DefaultSingletonBeanRegistry: SingletonBeanRegistry 인터페이스를 구현하고 다음과 같은 기능을 갖는 클래스 단일 인스턴스 Bean 함수를 직접 등록하고 가져옵니다.
  • ConfigurableBeanFactory: HierarchicalBeanFactory 및 SingletonBeanRegistry를 기반으로 상위 BeanFactory 설정, 클래스 로더(특정 클래스 로더를 지정하여 클래스를 로드할 수 있음을 나타냄) 및 Spring EL 표현식 파서 설정(BeanFactory가 EL 표현식을 구문 분석할 수 있음을 나타냄), 유형 변환 서비스 설정(BeanFactory가 유형 변환을 수행할 수 있음을 나타냄), BeanPostProcessor 추가(BeanFactory가 Bean 후처리기를 지원함을 나타냄), BeanDefinitions 병합, 삭제 Function
  • FactoryBeanRegistrySupport: FactoryBean의 기능을 지원합니다.
  • AutowireCapableBeanFactory: BeanFactory를 기반으로 Bean 생성 과정에서 Bean의 자동 어셈블리를 지원합니다.
  • AbstractBeanFactory: Con을 구현합니다. figurableBeanFactory 인터페이스는 FactoryBeanRegistrySupport를 상속합니다. 이 BeanFactory의 기능은 이미 매우 포괄적이지만 beanName을 자동으로 조립하고 얻을 수 없습니다.
  • AbstractBeanFactory를 상속하고 AutowireCapableBeanFactory를 구현하며
  • DefaultListableBeanFactory를 가지며 Config를 구현합니다. urableListableBeanFactory 인터페이스와 BeanDefinitionRegistry 인터페이스, 그래서 DefaultListableBeanFactory는 매우 강력합니다.
  • ApplicationContext
  • ApplicationContext는 인터페이스가 실제로 BeanFactory이지만 BeanFactory보다 더 정교합니다. 예:

HierarchicalBeanFactory:

부모 BeanFactory를 얻는 기능이 있습니다.

ListableBeanFactory:

beanNames을 얻는 기능이 있습니다
  • ResourcePatternResolver: 한 번에 여러 리소스(파일 리소스 등)를 얻을 수 있는 리소스 로더 등)
  • EnvironmentCapable: 런타임 환경을 얻을 수 있습니다. (런타임 환경 설정 기능 없음)
  • ApplicationEventPublisher: 이벤트 브로드캐스트 기능 있음(이벤트 리스너 추가 기능 없음)
  • MessageSource: 국제 기능 있음
  • ApplicationContext에는 두 가지 중요한 구현 클래스가 있습니다.
  • AnnotationConfigApplicationContext
ClassPathXmlApplicationContext

AnnotationConfigApplicationContext

    • ConfigurableApplicationContext:继承了ApplicationContext接口,增加了 添加事件监听器、添加BeanFactoryPostProcessor、设置Environment,获取ConfigurableListableBeanFactory等功能
    • AbstractApplicationContext:实现了ConfigurableApplicationContext接口
    • GenericApplicationContext:继承了AbstractApplicationContext,实现了BeanDefinitionRegistry接口,拥有所有ApplicationContext的功能,并且可以注册BeanDefinition,注意这个类中有一个属性(DefaultListableBeanFactory beanFactory)
    • AnnotationConfigRegistry:可以单独注册某个为类为BeanDefinition(可以处理该类上的**@Configuration注解**,已经可以处理**@Bean注解**),同时可以扫描
    • AnnotationConfigApplicationContext:继承了GenericApplicationContext,实现了AnnotationConfigRegistry接口,拥有了以上所有的功能

    ClassPathXmlApplicationContext

    Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석

    它也是继承了AbstractApplicationContext,但是相对于AnnotationConfigApplicationContext而言,功能没有AnnotationConfigApplicationContext强大,比如不能注册BeanDefinition

    资源加载

    ApplicationContext还拥有资源加载的功能,比如,可以直接利用ApplicationContext获取某个文件的内容:

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    
            Resource resource = context.getResource("file:/Users/xiexu/Library/Mobile Documents/com~apple~CloudDocs/SSM/day01/src/main/java/cn/xx/domain/User.java");
            System.out.println(resource.contentLength());
    
            Resource resource1 = context.getResource("https://www.baidu.com");
            System.out.println(resource1.contentLength());
            System.out.println(resource1.getURL());
    
            Resource resource2 = context.getResource("classpath:spring.xml");
            System.out.println(resource2.contentLength());
            System.out.println(resource2.getURL());
    
    				// 可以一次性获取多个
            Resource[] resources = context.getResources("classpath:cn/xx/domain/*.class");
            for (Resource resource3 : resources) {
                System.out.println(resource3.contentLength());
                System.out.println(resource3.getFilename());
            }

    事件发布

    先定义一个事件监听器:

    		@Bean
        public ApplicationListener applicationListener() {
            return new ApplicationListener() {
                @Override
                public void onApplicationEvent(ApplicationEvent event) {
                    System.out.println("接收到了一个事件");
                }
            };
        }

    然后发布一个事件:

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    
            context.publishEvent("kkk");

    类型转化

    在Spring源码中,有可能需要把String转成其他类型,所以在Spring源码中提供了一些技术来更方便的做对象的类型转化,关于类型转化的应用场景, 后续看源码的过程中会遇到很多。

    PropertyEditor

    这其实是JDK中提供的类型转化工具

    public class StringToUserPropertyEditor extends PropertyEditorSupport implements PropertyEditor {
    
        @Override
        public void setAsText(String text) throws IllegalArgumentException {
            User user = new User();
            user.setName(text);
            this.setValue(user);
        }
    
    }
    StringToUserPropertyEditor propertyEditor = new StringToUserPropertyEditor();
    propertyEditor.setAsText("1");
    User value = (User) propertyEditor.getValue();
    System.out.println(value);

    在Spring容器中注册 PropertyEditor:

    		@Bean
        public CustomEditorConfigurer customEditorConfigurer() {
            CustomEditorConfigurer customEditorConfigurer = new CustomEditorConfigurer();
            Map<Class<?>, Class<? extends PropertyEditor>> propertyEditorMap = new HashMap<>();
    
            /**
             * 表示StringToUserPropertyEditor可以将String转化成User类型,
             * 在Spring源码中,如果发现当前对象是String,而需要的类型是User,
             * 就会使用该PropertyEditor来做类型转化
             */
            propertyEditorMap.put(User.class, StringToUserPropertyEditor.class);
            customEditorConfigurer.setCustomEditors(propertyEditorMap);
            return customEditorConfigurer;
        }

    假设现在有如下 Bean:

    @Component
    public class Test {
    
        @Value("xiaoming")
        private User user;
    
        public void test() {
            System.out.println(user);
            System.out.println(user.getName());
        }
    }

    Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220906213724892

    ConversionService

    Spring中提供的类型转化服务,它比PropertyEditor更强大

    public class StringToUserConverter implements ConditionalGenericConverter {
    
        @Override
        public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
            return sourceType.getType().equals(String.class) && targetType.getType().equals(User.class);
        }
    
        @Override
        public Set<ConvertiblePair> getConvertibleTypes() {
            return Collections.singleton(new ConvertiblePair(String.class, User.class));
        }
    
        @Override
        public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
            User user = new User();
            user.setName((String) source);
            return user;
        }
    
    }
    DefaultConversionService conversionService = new DefaultConversionService();
    conversionService.addConverter(new StringToUserConverter());
    User value = conversionService.convert("1", User.class);
    System.out.println(value);

    在Spring中注册ConversionService:

    		@Bean
        public ConversionServiceFactoryBean conversionService() {
            ConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean();
            conversionServiceFactoryBean.setConverters(Collections.singleton(new StringToUserConverter()));
    
            return conversionServiceFactoryBean;
        }

    TypeConverter

    整合了PropertyEditor和ConversionService的功能,是Spring内部用的:

    SimpleTypeConverter typeConverter = new SimpleTypeConverter();
            typeConverter.registerCustomEditor(User.class, new StringToUserPropertyEditor());
            User value = typeConverter.convertIfNecessary("xxx", User.class);
            System.out.println(value);
            System.out.println(value.getName());
    SimpleTypeConverter typeConverter = new SimpleTypeConverter();
            DefaultConversionService conversionService = new DefaultConversionService();
            conversionService.addConverter(new StringToUserConverter());
            typeConverter.setConversionService(conversionService);
            User value = typeConverter.convertIfNecessary("xxx", User.class);
            System.out.println(value);
            System.out.println(value.getName());

    OrderComparator

    OrderComparator是Spring所提供的一种比较器,可以根据@Order注解或实现Ordered接口来进行值的比较,从而可以进行排序。

    public class A implements Ordered {
    
        @Override
        public int getOrder() {
            return 3;
        }
    
        @Override
        public String toString() {
            return this.getClass().getSimpleName();
        }
    }
    public class B implements Ordered {
    
        @Override
        public int getOrder() {
            return 2;
        }
    
        @Override
        public String toString() {
            return this.getClass().getSimpleName();
        }
    }
    public class Main {
    
        public static void main(String[] args) {
            A a = new A(); // order=3
            B b = new B(); // order=2
    
            OrderComparator comparator = new OrderComparator();
            System.out.println(comparator.compare(a, b));  // 1
    
            List list = new ArrayList<>();
            list.add(a);
            list.add(b);
    
            // 按order值升序排序
            list.sort(comparator);
    
            System.out.println(list);  // B,A
        }
    
    }

    另外,Spring中还提供了一个OrderComparator的子类:AnnotationAwareOrderComparator,它支持用@Order来指定order值。

    比如:

    @Order(3)
    public class A {
    
        @Override
        public String toString() {
            return this.getClass().getSimpleName();
        }
    
    }
    @Order(2)
    public class B {
    
        @Override
        public String toString() {
            return this.getClass().getSimpleName();
        }
    
    }
    public class Main {
    
        public static void main(String[] args) {
            A a = new A(); // order=3
            B b = new B(); // order=2
    
            AnnotationAwareOrderComparator comparator = new AnnotationAwareOrderComparator();
            System.out.println(comparator.compare(a, b)); // 1
    
            List list = new ArrayList<>();
            list.add(a);
            list.add(b);
    
            // 按order值升序排序
            list.sort(comparator);
    
            System.out.println(list); // B,A
        }
    
    }

    BeanPostProcessor

    BeanPostProcess 表示Bean的后置处理器,我们可以定义一个或多个BeanPostProcessor

    @Component
    public class XiexuBeanPostProcessor implements BeanPostProcessor {
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            if ("user".equals(beanName)) {
                System.out.println("初始化前");
            }
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if ("user".equals(beanName)) {
                System.out.println("初始化后");
            }
            return bean;
        }
    
    }

    一个BeanPostProcessor可以在任意一个Bean初始化前以及初始化后去额外的做一些用户自定义的逻辑,当然,我们可以通过判断beanName来进行针对性处理(针对某个Bean,或某部分Bean)。

    我们可以通过定义BeanPostProcessor来干涉Spring创建Bean的过程。

    BeanFactoryPostProcessor

    BeanFactoryPostProcessor表示Bean工厂的后置处理器,其实和BeanPostProcessor类似,BeanPostProcessor是干涉Bean的创建过程,BeanFactoryPostProcessor是干涉BeanFactory的创建过程。

    比如,我们可以这样定义一个BeanFactoryPostProcessor:

    @Component
    public class XiexuBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.out.println("加工beanFactory");
        }
    }

    可以在postProcessBeanFactory()方法中对BeanFactory进行加工。

    FactoryBean

    上面提到,我们可以通过BeanPostPorcessor来干涉Spring创建Bean的过程,但是如果我们想一个Bean完完全全由我们自己来创造,也是可以的,比如通过FactoryBean:

    @Component
    public class XiexuFactoryBean implements FactoryBean {
    
        @Override
        public Object getObject() throws Exception {
            User user = new User();
    
            return user;
        }
    
        @Override
        public Class<?> getObjectType() {
            return User.class;
        }
    }

    通过上面这段代码,我们自己创造了一个User对象,并且它将成为Bean。但是通过这种方式创造出来的User的Bean,只会经过初始化后,其他Spring的生命周期步骤是不会经过的,比如依赖注入。

    注意:单例池里面还是原来的xiexuFactoryBean,而通过getObject()方法返回的userBean是存放在factoryBeanObjectCache里面(缓存)。

    Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220907162114007

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
            // 如果beanName加上&,表示获取的是单例池里面的XiexuFactoryBean
            Object bean1 = context.getBean("&xiexuFactoryBean");
            System.out.println(bean1); // cn.xx.domain.XiexuFactoryBean@2de8284b
    
            // 如果beanName没有加上&,表示获取的是factoryBeanObjectCache缓存里面的userBean
            Object bean2 = context.getBean("xiexuFactoryBean");
            System.out.println(bean2); // cn.xx.domain.User@396e2f39

    有同学可能会想到,通过@Bean也可以自己生成一个对象作为Bean,那么和FactoryBean的区别是什么呢?其实在很多场景下他俩是可以替换的,但是站在原理层面来说,区别也很明显,@Bean定义的Bean是会经过完整的Bean生命周期的。

    ExcludeFilter 和 IncludeFilter

    这两个Filter是Spring扫描过程中用来过滤的。ExcludeFilter 表示排除过滤器IncludeFilter 表示包含过滤器

    比如以下配置,表示扫描cn.xx这个包下面的所有类,但是排除UserService类,

    就算UserService类上面有@Component注解也不会成为Bean。

    @ComponentScan(value = "cn.xx", 
            excludeFilters = {@ComponentScan.Filter(
                    type = FilterType.ASSIGNABLE_TYPE, 
                    classes = UserService.class)})
    public class AppConfig {
    }

    再比如以下配置,就算UserService类上没有@Component注解,它也会被扫描成为一个Bean。

    @ComponentScan(value = "cn.xx",
            includeFilters = {@ComponentScan.Filter(
                    type = FilterType.ASSIGNABLE_TYPE,
                    classes = UserService.class)})
    public class AppConfig {
    }

    FilterType分为:

    • ANNOTATION:表示是否包含某个注解
    • ASSIGNABLE_TYPE:表示是否是某个类
    • ASPECTJ:表示是否符合某个Aspectj表达式
    • REGEX:表示是否符合某个正则表达式
    • CUSTOM:自定义

    在Spring的扫描逻辑中,默认会添加一个AnnotationTypeFilterincludeFilters,表示默认情况下在Spring扫描过程中会认为类上有@Component注解的就是Bean。

    MetadataReader、ClassMetadata、AnnotationMetadata

    在Spring中需要去解析类的信息,比如类名、类中的方法、类上的注解,这些都可以称之为类的元数据,所以Spring中对类的元数据做了抽象,并提供了一些工具类。

    MetadataReader表示类的元数据读取器,默认实现类为SimpleMetadataReader。比如:

    public class Test {
    
        public static void main(String[] args) throws IOException {
            SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();
    
            // 构造一个MetadataReader
            MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("cn.xx.service.impl.UserServiceImpl");
    
            // 得到一个ClassMetadata,并获取了类名
            ClassMetadata classMetadata = metadataReader.getClassMetadata();
    
            System.out.println(classMetadata.getClassName());
    
            // 获取一个AnnotationMetadata,并获取类上的注解信息
            AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
            for (String annotationType : annotationMetadata.getAnnotationTypes()) {
                System.out.println(annotationType);
            }
        }
    }

    5.Spring之Bean生命周期源码解析

    Spring 扫描底层流程(doScan方法)

    • 扫描包路径,得到包路径下的所有class文件对象(注意,这里不是指Class对象,而是文件对象,可以理解为File对象)
    • 利用ASM技术解析每个class文件对象,得到class元数据信息
    • 如果当前类和某个excludeFilter匹配,那就排除这个类;如果当前类和某个includeFilter匹配,那就获取这个类(默认情况下,Spring会有一个@Component注解的includeFilter)
    • 进一步进行条件注解@Conditional的匹配筛选
    • 都匹配成功后,根据当前类生成一个ScannedGenericBeanDefinition
    • 然后判断如果该类不是顶级类或者静态内部类,则不通过;如果该类是抽象类或者接口类,则不通过;如果该类是抽象类并且该类中有@Lookup注解的方法,则通过。
    • 最终扫描到某些BeanDefinition
    • 遍历每个BeanDefinition,解析每个类的@Scope内容并设置到对应的BeanDefinition中
    • 设置AnnotationBeanNameGenerator生成beanName(解析@Component注解所指定的beanName,如果没有指定则默认生成「该类名字的第一个字母小写」;如果该类的前两个字母都是大写,则beanName就是该类的名字)
    • 给BeanDefinition对象中的属性赋默认值
    • 解析@Lazy@Primary@DependsOn@Role@Description 等注解并赋值给BeanDefinition对应的属性
    • 判断当前beanName是否存在Spring容器中,如果不存在则把beanName和BeanDefinition注册到Spring容器中(也就是存入beanDefinitionMap);如果存在则会有两种方案:
      • 如果已经存在的BeanDefinition对应的类型和扫描到的BeanDefinition对应的类型相同的话(兼容),则直接返回false而不会抛出异常。
      • 如果已经存在的BeanDefinition对应的类型和扫描到的BeanDefinition对应的类型不相同的话(不兼容),则会报错并抛出异常。
    • 扫描结束。

    生成BeanDefinition

    • 首先通过ResourcePatternResolver获得指定包路径下的所有.class文件(Spring源码中将此文件包装成了Resource对象)
    • 遍历每个Resource对象利用MetadataReaderFactory解析Resource对象得到MetadataReader(在Spring源码中MetadataReaderFactory具体的实现类为CachingMetadataReaderFactory,MetadataReader的具体实现类为SimpleMetadataReader)
    • 利用MetadataReader进行excludeFiltersincludeFilters,以及条件注解@Conditional的筛选(某个类上是否存在@Conditional注解,如果存在则调用注解中所指定的类的match方法进行匹配,匹配成功则通过筛选,匹配失败则pass掉)
    • 筛选通过后,基于metadataReader生成ScannedGenericBeanDefinition再基于metadataReader判断对应的类是不是接口或抽象类
    • 如果筛选通过,就表示扫描到了一个Bean,将ScannedGenericBeanDefinition加入结果集

    注意:

    上面说的是通过扫描得到BeanDefinition对象,我们还可以通过直接定义BeanDefinition,或解析spring.xml文件的<bean></bean>,或者@Bean注解得到BeanDefinition对象。

    MetadataReader 表示类的元数据读取器,主要包含了一个AnnotationMetadata,功能有

    • 获取类的名字
    • 获取父类的名字
    • 获取所实现的所有接口名
    • 获取所有内部类的名字
    • 判断是不是抽象类
    • 判断是不是接口
    • 判断是不是一个注解
    • 获取拥有某个注解的方法集合
    • 获取类上添加的所有注解信息
    • 获取类上添加的所有注解类型集合

    注意:

    CachingMetadataReaderFactory解析某个.class文件得到MetadataReader对象是利用 ASM 技术,并没有加载这个类到JVM中。并且最终得到的ScannedGenericBeanDefinition对象,它的 beanClass 属性存储的是当前类的名字,而不是class对象。(beanClass属性的类型是Object,它即可以存储类的名字,也可以存储类对象)

    合并BeanDefinition

    通过扫描得到所有的BeanDefinition之后,就可以根据BeanDefinition创建Bean对象了。在Spring中支持父子BeanDefinition,和Java子父类类似。

    父子BeanDefinition实际上用得比较少,例如:这么定义的情况下,child是单例Bean。

    <bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
    <bean id="child" class="com.zhouyu.service.Child"/>

    但如果是下面这样,child就是原型Bean了。

    <bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
    <bean id="child" class="com.zhouyu.service.Child" parent="parent"/>

    因为child的父BeanDefinition是parent,所以会继承parent上所定义的scope属性。

    所以在根据child来生成Bean对象之前,需要进行BeanDefinition的合并,才能得到完整的child的BeanDefinition。

    加载类

    BeanDefinition合并之后,就可以去创建Bean对象了,而创建Bean就必须实例化对象,而实例化就必须先加载当前BeanDefinition所对应的class,在AbstractAutowireCapableBeanFactory类的createBean()方法中,一开始就会调用:

    Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220926221933600

    Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220926222050533

    public boolean hasBeanClass() {
    		// 判断当前BeanDefinition的beanClass属性,是不是Class类型
    		return (this.beanClass instanceof Class);
    	}

    如果beanClass属性的类型是Class,那么就直接返回;如果不是,则会根据类名进行加载(doResolveBeanClass方法所做的事情)

    Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220926223604150

    	@Override
    	@Nullable
    	public ClassLoader getBeanClassLoader() {
    		return this.beanClassLoader;
    	}
    
    	@Nullable
    	private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();

    先利用BeanFactory所设置的类加载器来加载类,如果没有设置,则默认使用ClassUtils.getDefaultClassLoader()所返回的类加载器来进行加载。

/** * 获取默认的类加载器 */@Nullablepublic static ClassLoader getDefaultClassLoader() {ClassLoader cl = null;/** * 优先获取线程中的类加载器 * 一开始,tomcat会将自定义的类加载器设置到线程上下文中, * 然后当你走到这一步的时候,就可以获取到线程中的tomcat自定义类加载器 */try {cl = Thread.currentThread().getContextClassLoader();} catch (Throwable ex) {}// 如果线程上下文中的类加载器为空,那就获取ClassUtils类所对应的类加载器if (cl == null) {cl = ClassUtils.class.getClassLoader();if (cl == null) { // 如果类加载器等于null,就说明是引导类加载器// ClassUtils类是被Bootstrap类加载器加载的,则获取系统类加载器try {cl = ClassLoader.getSystemClassLoader();} catch (Throwable ex) {}}}// 返回类加载器return cl;}

ClassUtils.getDefaultClassLoader()

优先返回当前线程中的类加载器如果当前线程中的类加载器为空,则返回ClassUtils类的类加载器如果ClassUtils类的类加载器为空,那么表示是Bootstrap类加载器加载的ClassUtils类,那么则返回系统类加载器 4.实例化前

当前BeanDefinition对应的类加载成功后,就可以实例化对象了,但是…

在实例化对象之前,Spring提供了一个扩展点,允许用户来控制是否在某些Bean实例化之前做一些启动动作。

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220926231603057

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220926232155295

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220926232420898

这个扩展点叫InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation( )。比如:

@Componentpublic class ZhouyuBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException {    if ("userService".equals(beanName)) {     System.out.println("实例化前");    }    return null;  }  }

以上代码会导致,在userService这个Bean实例化前,会进行打印。

注意:postProcessBeforeInstantiation()是有返回值的,如果这么实现:

@Componentpublic class ZhouyuBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException {    if ("userService".equals(beanName)) {     System.out.println("实例化前");     return new UserService();    }  return null; }  }

userService这个Bean在实例化前会直接返回一个由我们所定义的UserService对象。如果是这样,表示不需要Spring来实例化了,并且后续的Spring依赖注入也不会进行了,会跳过一些步骤,直接执行初始化后这一步。

5.实例化

在这个步骤中就会根据BeanDefinition去创建一个对象了。

6.BeanDefinition的后置处理

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220926234536686

Bean对象实例化之后,接下来就应该给对象的属性赋值了。在真正给属性赋值之前,Spring又提供了一个扩展点MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition( ),可以对此时的BeanDefinition进行加工,比如:

@Componentpublic class ZhouyuMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor { @Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName) {  if ("userService".equals(beanName)) {   beanDefinition.getPropertyValues().add("orderService", new OrderService()); // 注入属性  } }  }

在Spring源码中,AutowiredAnnotationBeanPostProcessor 就是一个MergedBeanDefinitionPostProcessor,它的postProcessMergedBeanDefinition()方法中会去查找注入点,并缓存在AutowiredAnnotationBeanPostProcessor对象的一个Map中(injectionMetadataCache)。

7.实例化后

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220927001402231

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220927001432634

在处理完BeanDefinition后,Spring又设计了一个扩展点:InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation( ),比如:

@Componentpublic class ZhouyuInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {  if ("userService".equals(beanName)) {   UserService userService = (UserService) bean;   userService.test();  }  return true; }}

上述代码就是对userService所实例化出来的对象进行处理。

注意:这个扩展点在Spring源码中基本没有怎么使用。

8.自动注入 9.处理属性

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220927002120020

/** * 这里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法,会直接给对象中的属性赋值 * AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了 * 并不会处理pvs指的是: * 如果当前bean的某些属性已经通过postProcessMergedBeanDefinition方法注入了,那么该属性上面的@Autowired注解应该是无效的, * 因为程序员已经将自定义的值设置到属性里面去了 */

这个步骤中,就会处理@Autowired@Resource@Value等注解,也是通过**InstantiationAwareBeanPostProcessor.postProcessProperties( )**扩展点来实现的。

比如:我们甚至可以实现一个自己的自动注入功能

@Componentpublic class ZhouyuInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {if ("userService".equals(beanName)) {for (Field field : bean.getClass().getFields()) {if (field.isAnnotationPresent(ZhouyuInject.class)) {field.setAccessible(true);try {field.set(bean, "123");} catch (IllegalAccessException e) {e.printStackTrace();}}}}return pvs;}}

10.执行Aware

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220927003155088

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220927003137255

完成了属性赋值之后,Spring会执行一些回调,包括:

BeanNameAware:回传beanName给bean对象BeanClassLoaderAware:回传classLoader给bean对象BeanFactoryAware:回传beanFactory给对象 11.初始化前

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220927003420161

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220927003447488

初始化前,也是Spring提供的一个扩展点:BeanPostProcessor.postProcessBeforeInitialization( ),比如:

@Componentpublic class ZhouyuBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  if ("userService".equals(beanName)) {   System.out.println("初始化前");  }  return bean; }}

利用初始化前,可以对已经进行了依赖注入的Bean进行处理。

在Spring源码中:

InitDestroyAnnotationBeanPostProcessor 会在初始化前这个步骤中执行@PostConstruct的方法,ApplicationContextAwareProcessor 会在初始化前这个步骤中进行其他Aware的回调: EnvironmentAware:回传环境变量EmbeddedValueResolverAware:回传占位符解析器ResourceLoaderAware:回传资源加载器ApplicationEventPublisherAware:回传事件发布器MessageSourceAware:回传国际化资源ApplicationStartupAware:回传应用其他监听对象,可忽略ApplicationContextAware:回传Spring容器ApplicationContext 12.初始化

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220927003759721

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220927003907501

查看当前Bean对象是否实现了InitializingBean接口,如果实现了就调用其afterPropertiesSet()方法执行BeanDefinition中指定的初始化方法 13.初始化后

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220927004002073

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220927004022427

这是Bean创建生命周期中的最后一个步骤,也是Spring提供的一个扩展点:BeanPostProcessor.postProcessAfterInitialization( ),比如:

@Componentpublic class ZhouyuBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  if ("userService".equals(beanName)) {   System.out.println("初始化后");  }  return bean; }}

可以在这个步骤中,对Bean进行最终处理,Spring中的AOP就是基于初始化后实现的,初始化后返回的对象才是最终的Bean对象

14.总结BeanPostProcessor

实例化前:

InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()

实例化

MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()

实例化后:

InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()

自动注入

InstantiationAwareBeanPostProcessor.postProcessProperties()

Aware对象

初始化前:

BeanPostProcessor.postProcessBeforeInitialization()

初始化

初始化后:

BeanPostProcessor.postProcessAfterInitialization()

Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석-20220927004746839

推荐学习:《java视频教程

위 내용은 Java Spring으로 생성된 Bean의 Life Cycle에 대한 상세한 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 jb51.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제