昨天晚上看spring In Action这本书,说spring会调用默认的构造函数来生成bean实例,如果该默认的构造函数为私有的时候,我们可以指定factory-method来生成实例。我试了一下,下面是代码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类型的 <bean id="subBean" class="test.SubBean" scope="prototype"></bean>这个事测试类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

解决方案 »

  1.   

    是作用域的问题
    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环境.
      

  2.   

    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来绕开这些保护机制,那不是很容易搬起石头砸自己脚么?
      

  3.   

    看看
    public class Test {
    private Test() {
    }public int add(int param1, int param2) {
    return param1 + param2;
    }public String echo(String msg) {
    return "echo:" + msg;
    }public static void main(String[] args) throws Exception {
    Class classType = Test.class;
    Object invokeTester = classType.newInstance();
    // 调用InvokeTester对象的add()方法
    Method addMethod = classType.getMethod("add", new Class[] { int.class,
    int.class });
    Object result = addMethod.invoke(invokeTester, new Object[] {
    new Integer(100), new Integer(200) });
    System.out.println((Integer) result);
    // 调用InvokeTester对象的echo()方法
    Method echoMethod = classType.getMethod("echo",
    new Class[] { String.class });
    result = echoMethod.invoke(invokeTester, new Object[] { "Hello" });
    System.out.println((String) result);
    }
    }
      

  4.   

    谢谢啊!看来还是对jdk不熟,我尝试使用Class.getDeclaredMethod()来调用构造方法,所以没有成功!这只是看书的时候的练习,我只收想知道spring到底是怎么去实例化bean的,平常实际应用肯定不会做这种自相矛盾的事情