相信用过spring的人肯定写过这样一段代码:
Resource resource = new FileSystemResource("res/springconf.xml");
BeanFactory factory = new XmlBeanFactory(resource);
HelloBean helloBean = (HelloBean)factory.getBean("helloBean");
System.out.println(helloBean.getSpringInfo());
当然Bean和XML有可能不同,下面贴出我写的一个简单的HelloBean和一个简单的spring配置文件springconf.xml:
HelloBean.java:
package com.spring.entrance;
public class HelloBean
{
private String springInfo;
/**
* 显示的public构造函数
*/
public HelloBean()
{
System.out.println("构造函数初始化");
}
/**
*
* setter
*
* @param info
*/
public void setSpringInfo(String info)
{
this.springInfo = info;
}
/**
*
* getter
*
* @return
*/
public String getSpringInfo()
{
return springInfo;
}
}
springconf.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean name="helloBean" class="com.spring.entrance.HelloBean">
<property name="springInfo" value="hello,spring" />
</bean>
</beans>
大家仔细看一下,我特意在构造函数这里添加了一句打印信息,因为我想看看spring容器是如何初始化对象的。输出结果显而易见,首先执行执行了构造函数的打印语句,然后打印出了配置文件注入的属性值。不过马上我要和大家讨论的是,如果我将HelloBean的构造函数改成私有的构造函数 结果会怎么样呢?
于是我将HelloBean的构造函数的修饰符public改成了private ,然后运行,看结果,令我很诧异,构造函数中的打印语句仍然执行 。让我诧异的原因是spring容器竟然可以调用我的私有构造函数 。起初,我想到这个问题是因为在做项目的时候,我想做一个单例的管理器,即构造函数私有,然后利用懒汉式或者饿汉式的方式来创建单例对象。不过因为项目的原因,一些类的实例化工作是利用spring做的,即你只需要在xml中配置一个bean即可。
这让我对spring容器有了莫大的兴趣,发现之前对spring的理解有许多的不足,下面我就解惑spring到底是如何创建对象的:
首先可以肯定的是,spring是利用反射机制 来创建对象的,可到底是怎么样利用反射创建的?下面我再写一个demo:
package com.spring.entrance;
import java.lang.reflect.Constructor;
/**
*
* 利用反射构造私有类对象
*
* @author landon
*
*/
public class ReflectConstructDemo
{
public static void main(String...args)
{
try
{
Constructor [] constructors = Class.forName("com.spring.entrance.HelloBean").getDeclaredConstructors();
for(int i = 0;i < constructors.length;i++)
{
constructors[i].newInstance();
}
}
catch(SecurityException e)
{
System.out.println(e.getMessage());
}
catch(ClassNotFoundException e)
{
System.out.println(e.getMessage());
}
catch(Exception e)
{
e.printStackTrace();
}
}
}