标签:单例模式 nbsp ack 默认 tac print 类的构造函数 需求 .com
首先明白,spring的IOC功能需要是利用反射原理,反射获取类的无参构造方法创建对象,如果一个类没有无参的构造方法spring是不会创建对象的。在这里需要提醒一下,如果我们在class中没有显示的声明构造方法,默认会生成一个无参构造方法,但是当我们显示的声明一个有参构造方法的时候,JVM不会帮我们生成无参构造方法,所以我们声明一个带参数的构造方法也需要声明一个无参构造方法。(题外话:如果父类声明一个有参构造方法,子类需要在构造方法第一行显示的调用父类构造方法,因为子类的对象也是父类的对象,所以在创建子类对象的同时也会创建父类的对象,如果父类有默认的无参构造函数,JVM会调用无参构造函数,但是有了有参的就需要我们在子类的构造函数中调用父类的有参构造函数)
No default constructor found; nested exception is java.lang.NoSuchMethodException: zd.dms.job.ebuy.Person.<init>()
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{ /** * */ private static final long serialVersionUID = -8934360924125349297L; @Autowired private GroupAndUserService groupAndUserService; @Autowired private Person 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容器中只有一个这个对象。
销毁的时候的结果:
---------------这是@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方法
-----------------------多模式的xml配置以及结果---------------------------------------:
配置:
<bean id="person" class="zd.dms.job.ebuy.Person" autowire="byType" destroy-method="destory" init-method="init" scope="prototype"></bean>
我们多次访问Action,所以Action会多次调用Person对象,发现会多次创建Person对象,也就是请求一次会创建一个对象,也就是多例:
至于到底是该使用单例还是多例,这就需要我们平时的业务需求了,springMvc就是单例的,struts2默认就是多例的。我们也可以使用注解配置单例和多例,如下:
配置如下:
Action是struts默认多例:(注入Person类对象)
Person类模拟是service层,默认是单例(注入GroupDaoImpl对象)
GroupDaoImpl是多例
也就是我们上面的配置从Action到service到dao的作用域是多-单-多,我们多次访问Action,结果如下:
解释:
我们每次访问action是多例所以每次会创建对象,而Person默认是单例,所以spring只会维护一个对象,即使GroupDaoImpl是多例模式,但是其已经注入到Person类中,而person不会创建新的对象,所以GroupDaoImpl也只会生成一个对象。只有在生成Person类的时候才会重新生成GroupDaoImpl且重新维护关系。所以上面在spring中出现对各TestAction,一个Person和一个GroupDaoImpl。
Spring中构造器、init-method、@PostConstruct、afterPropertiesSet孰先孰后,自动注入发生时间以及单例多例的区别
标签:单例模式 nbsp ack 默认 tac print 类的构造函数 需求 .com
原文地址:https://www.cnblogs.com/qlqwjy/p/9417034.html