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