spring的生命周期

对于spring的生命周期,在宏观角度来看:

    可以分为实例化前、实例化、实例化后、初始化前、初始化、初始化后。

           在详细角度来看:

    可以分为1.生成BeanDefinition    2.合并BeanDefinition   3.加载类   4.实例化前   5.推断构造方法   6.实例化    

        7.BeanDefinition的后置处理    8.填充属性    9.执行Aware(BeanNameAware、BeanClassLoadAware、BeanFactoryAware)   

        10.初始化前 (ApplicationContextAwareProcessor、InitDestoryAnnotationBeanPostProcessor)  11.初始化   12、初始化后。

 

==================================================

在讲生命周期之前,我们要先了解一下什么是BeanPostProcessor。他可以在bean的实例化、初始化前后加入自定义的一些逻辑。

 

 

 

 可以从继承体系中看到,BeanPostProcessor有很多的接口被继承,我们可以将这些类分为三个功能。

 

 

 我们可以拿BeanPostProcessor这个接口来验证,它是否是应用于初始化。

 

@Component
public class WxyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("userService")){
            System.out.println("实例化之前UserService");
        }
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("userService")){
            System.out.println("实例化后UserService");
        }
        return null;
    }

}


@Component
public class UserService {
    public UserService() {
        System.out.println("实例化");
    }
    
}

 

 这个例子其实并不能证明他是在初始化前后使用,但是能证明它是在实例化之后进行的。

 

=============================================================================================

接下来我们可以来讲spring的生命周期。

实例化前、后:

  我们可以使用InstantiationAwareBeanPostProcessor接口来验证是否是在初始化前后调用。

@Component
public class WxyBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

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

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("userService")){
            System.out.println("实例化之后");
        }
        return false;
    }
}
@Component
public class UserService {
    public UserService() {
        System.out.println("实例化");
    }

}

 

 从结果中可以看出来,确实是在实例化前后进行调用。

 

 

实例化:

@Component
public class UserService {
    private User user;

    public UserService(){
        System.out.println("无参数实例化");
    }

    public UserService(User user){
        System.out.println("1个参数实例化");
    }
}

调用的是无参数实例化

@Component
public class UserService {
    private User user;

    public UserService(User user){
        System.out.println("1个参数实例化");
    }

    public UserService(User user,User user1){
        System.out.println("2个参数实例化");
    }
}

因为没有指定,所以会报错

@Component
public class UserService {
    private User user;

    public UserService(User user){
        System.out.println("1个参数实例化");
    }
    @Autowired
    public UserService(User user,User user1){
        System.out.println("2个参数实例化");
    }
}

调用1个参数实例化的构造方法,因为进行了指定

@Component
public class UserService {
    private User user;

    @Autowired
    public UserService(User user){
        System.out.println("1个参数实例化");
    }
    @Autowired
    public UserService(User user,User user1){
        System.out.println("2个参数实例化");
    }
}

会报错,因为都进行了指定,系统不知道要选择哪个

@Component
public class UserService {
    private User user;

    @Autowired(required = false)
    public UserService(User user){
        System.out.println("1个参数实例化");
    }
    @Autowired(required = false)
    public UserService(User user,User user1){
        System.out.println("2个参数实例化");
    }
}

会调用2个参数的构造方法,因为required=false的意思表示非必要

 

 

@ComponentScan("wxy")
public class Config {
    @Bean
    public User user(){
        return new User();
    }
    @Bean
    public User user1(){
        return new User();
    }
}
@Component
public class UserService {
    private User user;


    public UserService(User user){
        System.out.println("1个参数实例化");
    }
    @Autowired(required = true)
    public UserService(User user,User user1){
        System.out.println("2个参数实例化");
    }
}

会调用2个参数实例化的构造方法,Autowired是先找类型,找到类型之后数量有多个,则开始找名字相同的。

 

@ComponentScan("wxy")
public class Config {
    @Bean
    public User user(){
        return new User();
    }
    @Bean
    public User user2(){
        return new User();
    }
}
@Component
public class UserService {
    private User user;


    public UserService(User user){
        System.out.println("1个参数实例化");
    }
    @Autowired(required = true)
    public UserService(User user,User user1){
        System.out.println("2个参数实例化");
    }
}

这样会报错,因为容器中有user、user2的bean,然后构造方法中有user1这是没有的。

 

============================================================

实例化后:

@Component
public class BeanPostProcessor1 implements InstantiationAwareBeanPostProcessor {

    //实例化前
    @Override
    public Object postProcessBeforeInstantiation(Class<?> aClass, String beanName) throws BeansException {

        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if(beanName.equals("userService")){
            System.out.println("实例化后-----");
        }
        return true;
    }
}

这个是实现InstantiationAwareBeanPostProcessor 类的方法,postProcessAfterInstantiation是实例化后的方法,注意到它的返回值是boolean,false表示实例化后不需要走spring的属性注入,如果是true表示还需要属性注入。

@Component
public class UserService {


    private User user;


    @Autowired
    public void aaa(User user){
        System.out.println("set注入");
        this.user = user;
    }

}

 

 

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if(beanName.equals("userService")){
            System.out.println("实例化后-----");
        }
        return false;
    }

 

 

 

=================================

初始化

初始化的方式有2种,一种是实现InitializingBean接口的afterPropertiesSet方法,这个方法是在属性注入之后调用,一般用来做校验。

方式1:

@Component
public class UserService implements InitializingBean {
    private User user;
    public UserService() {
        System.out.println("实例化");

    }
    @Autowired
    public void setUser(User user) {
        System.out.println("属性注入:set方法注入");
        this.user = user;
    }

//    @PostConstruct
//    public void xxx(){
//        System.out.println("初始化方式1");
//    }


    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("初始化方式2");
    }
}
@Component
public class WxyBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

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

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("userService")){
            System.out.println("实例化之后");
        }
        return true;
    }
   //BeanPostProcess的实现方法---初始化之后
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("userService")){
            System.out.println("初始化之前");
        }
        return bean;
    }
//BeanPostProcess的实现方法---初始化之前
@Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (beanName.equals("userService")){ System.out.println("初始化之后"); } return null; } }

 

 通过结果能看到结果打印“初始化方式2”。

 

方式2:通过使用注解@PostConstruct进行初始化,但是有一个责任链模式,如果初始化前的postProcessBeforeInitialization方法返回值是bean,那么被注解@PostConstruct修饰的方法则可以运行,如果方法返回值是null,则不执行该方法。

        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.2</version>
        </dependency>
@Component
public class UserService implements InitializingBean {
    private User user;
    public UserService() {
        System.out.println("实例化");

    }
    @Autowired
    public void setUser(User user) {
        System.out.println("属性注入:set方法注入");
        this.user = user;
    }

    @PostConstruct
    public void xxx(){
        System.out.println("初始化方式1");
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("初始化方式2");
    }
}
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("userService")){
            System.out.println("初始化之前");
        }
        return null;
    }

 

 可以从结果看到,“初始化方法1”没有打印,说明xxx方法没有被执行。

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

 

 可以从结果看到,“初始化方法1”有打印,说明xxx方法被执行。

 

posted @ 2022-02-14 20:52  WXY_WXY  阅读(5342)  评论(0编辑  收藏  举报