Spring中構造器、init-method、@PostConstruct、afterPropertiesSet孰先孰後,自動注入發生時間以及單例多例的區別、SSH線程安全問題 - QiaoZhi - 博客園
https://www.cnblogs.com/qlqwjy/p/9417034.html
Spring中構造器、init-method、@PostConstruct、afterPropertiesSet孰先孰後
首先明白,spring的IOC功能需要是利用反射原理,反射獲取類的無參構造方法創建對象,如果一個類沒有無參的構造方法spring是不會創建對象的。在這裏需要提醒一下,如果我們在class中沒有顯示的聲明構造方法,默認會生成一個無參構造方法,但是當我們顯示的聲明一個有參構造方法的時候,JVM不會幫我們生成無參構造方法,所以我們聲明一個帶參數的構造方法也需要聲明一個無參構造方法。(題外話:如果父類聲明一個有參構造方法,子類需要在構造方法第一行顯示的調用父類構造方法,因爲子類的對象也是父類的對象,所以在創建子類對象的同時也會創建父類的對象,如果父類有默認的無參構造函數,JVM會調用無參構造函數,但是有了有參的就需要我們在子類的構造函數中調用父類的有參構造函數)
1.Person類只有一個有參構造方法,報錯如下:
No default constructor found; nested exception is java.lang.NoSuchMethodException: zd.dms.job.ebuy.Person.<init>()
2.大體知道有三種生命週期回調方法去參與到spring的生命週期,查閱了一下如下:(創建和銷燬的執行順序也是下面順序)
- 在指定方法上加上@PostConstruct 或@PreDestroy註解來制定該方法是在初始化之後還是銷燬之前調用。
- 通過實現 InitializingBean/DisposableBean 接口來定製初始化之後/銷燬之前的操作方法;
- 通過 <bean> 元素的 init-method/destroy-method屬性指定初始化之後 /銷燬之前調用的操作方法;
3.測試spring的順序與注入的順序與單例多例的問題
1.Person.java
package zd.dms.job.ebuy; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import zd.dms.dao.ebuy.GroupDao; public class Person implements InitializingBean,DisposableBean{ private String name; @Autowired private GroupDao groupDao; public Person() { System.out.println("---------------實例化一個Person對象----------"); System.out.println("---------------groupDao is -----------"+groupDao); } public void init() { System.out.println("------------這是xml的init方法----------...."); System.out.println("---------------groupDao is -----------"+groupDao); } public void destory() { System.out.println("---------------這是xml的destroy方法...."); System.out.println("---------------groupDao is -----------"+groupDao); } @PostConstruct public void init2() { System.out.println("------------這是@PostConstruct的init方法----------...."); System.out.println("---------------groupDao is -----------"+groupDao); } @PreDestroy public void destory2() { System.out.println("---------------這是@PreDestroy的destroy方法...."); System.out.println("---------------groupDao is -----------"+groupDao); } @Override public void destroy() throws Exception { System.out.println("-----------這是DisposableBean的destroy方法...."); System.out.println("---------------groupDao is -----------"+groupDao); } @Override public void afterPropertiesSet() throws Exception { System.out.println("-------這是InitializingBean的afterPropertiesSet方法...."); System.out.println("---------------groupDao is -----------"+groupDao); } }
-----------------------單例模式的xml配置以及結果---------------------------------------:
配置:
<bean id="person" class="zd.dms.job.ebuy.Person" autowire="byType" destroy-method="destory" init-method="init"></bean>
測試:將Person類注入到Action我們訪問Action
@Namespace("/qlqTest") @SuppressWarnings("all") public class TestAction extends DMSActionSupport { @Autowired private Person person; /** * */ private static final long serialVersionUID = -8934360924125349297L; @Autowired private GroupAndUserService groupAndUserService; private Map resultMap; @Action("test") public String testAction() { person.getClass(); return "js"; } }
當我們第一次訪問該Action會創建Person對象,打印結果如下:
- ---------------實例化一個Person對象---------- ---------------groupDao is -----------null ------------這是@PostConstruct的init方法----------.... ---------------groupDao is -----------zd.dms.dao.ebuy.GroupDaoImpl@435598e3 -------這是InitializingBean的afterPropertiesSet方法.... ---------------groupDao is -----------zd.dms.dao.ebuy.GroupDaoImpl@435598e3 ------------這是xml的init方法----------.... ---------------groupDao is -----------zd.dms.dao.ebuy.GroupDaoImpl@435598e3
證明對象創建的順序:
構造器-->自動注入-->@PostConstrut-->InitializingBean-->xml中配置init方法
再次調用不會打印,證明默認是單例的 singleton,也就是無論我們訪問多少次Action,Spring容器中只有一個這個Person實例對象。
銷燬的時候的結果:
---------------這是@PreDestroy的destroy方法.... ---------------groupDao is -----------zd.dms.dao.ebuy.GroupDaoImpl@435598e3 -----------這是DisposableBean的destroy方法.... ---------------groupDao is -----------zd.dms.dao.ebuy.GroupDaoImpl@435598e3 ---------------這是xml的destroy方法.... ---------------groupDao is -----------zd.dms.dao.ebuy.GroupDaoImpl@435598e3
所以銷燬順序爲:
@PreDestroy--DisposableBean-->xml中destroy-method方法