当前位置: 代码迷 >> J2EE >> spring到底是如何生成bean实例的
  详细解决方案

spring到底是如何生成bean实例的

热度:81   发布时间:2016-04-22 01:48:26.0
spring到底是怎么生成bean实例的
昨天晚上看spring In Action这本书,说spring会调用默认的构造函数来生成bean实例,如果该默认的构造函数为私有的时候,我们可以指定factory-method来生成实例。我试了一下,下面是代码
Java code
public class SubBean {    private static SubBean instance = null;    private SubBean() {             System.out.println("this is private constructor");    }    public static synchronized SubBean getInstance() {        if (instance == null) {            instance = new SubBean();        }        return instance;    }}

在配置文件中这么定义的bean,bean定义为prototype类型的
XML code
    <bean id="subBean" class="test.SubBean" scope="prototype"></bean>

这个事测试类
Java code
public class Test {    public static void main(String[] args) {        ApplicationContext context = new FileSystemXmlApplicationContext(                "D:/workspace/flex/opview/src/main/java/test/application.xml");        SubBean bean = (SubBean) context.getBean("subBean");        SubBean bean1 = (SubBean) context.getBean("subBean");        System.out.println(bean == bean1);    }}

subBean是一个单例,但是打印出来的结果是
this is private constructor
this is private constructor
this is private constructor
false
false说明bean和bean1不是指向同一个对象的,而且私有的构造方法也被调用了
如果xml文件中给bean加一个factory-method="getInstance"属性,那么打印出来的结果就是true

------解决方案--------------------
是作用域的问题
singleton 在spring IOC容器中仅存在一个Bean实例,Bean以单实例的方式存在.


prototype 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行new XxxBean()的操作.


request 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于webApplicationContext环境.


session 同一个HTTP session共享一个Bean,不同HTTP session使用不同的Bean,该作用域仅适用于webApplicationContext环境.


globalSession 同一个全局session共享一个Bean,一般用于portlet应用环境,该作用域仅适用于webApplicationContext环境.
------解决方案--------------------
Spring是利用反射去初始化化类的。私有的属性反射也是可以访问到的,类似:

//get Constructor
Class clazz = Class.forName("T");
Constructor cons = clazz.getDeclaredConstructor(null);

//set accessble to access private constructor
cons.setAccessible(true);
cons.newInstance(null);


只不过不建议你这么利用Spring而已。
因为既然你指定了构造函数为私有,说明你设计上有特殊考虑,不希望构造函数被直接调用,比如要准备某些静态资源、共享环境或其它事情,所以希望用工厂模式来做。然后你又借助Spring来绕开这些保护机制,那不是很容易搬起石头砸自己脚么?
  相关解决方案