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方法