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方法被執行。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM