模拟Spring的内部原理读取配置文件,实例化
2012-04-27 23:06
411 查看
先写一个xml文件:beans.xml
<beans>
<bean id="u" class="com.msb.dao.UserDAOImpl" />
<bean id="userService" class="com.msb.service.UserService" >
<property name="userDAO" bean="u"/>
</bean>
</beans>
这段代码的意图就是先声明一个id为u的bean,再声明一个id为userService的bean,同时,打算把u注入到userService当中,并成为它的userDAO属性。
实现这一环节,就需要一个类来完成这项工作,我们用ClassPathXMLApplicationContext来做。
先写一个接口:
public interface BeanFactory {
public Object getBean(String name);
}
通过这个接口,拿到bean实例
public class ClassPathXMLApplicationContext implements BeanFactory {
private Map<String,Object> beans = new HashMap<String,Object>();
public ClassPathXMLApplicationContext(){ //在构造方法中
SAXBuilder sb=new SAXBuilder();
Document doc;
try {
doc = sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml"));
Element root=doc.getRootElement(); //获取根元素HD
List list=root.getChildren("bean");//找到标签为bean的节点
for(int i=0;i<list.size();i++){ //找到每一个bean
Element element=(Element)list.get(i);
String id=element.getAttributeValue("id"); //拿到它的id
String clazz=element.getAttributeValue("class"); //拿到它的class
Object o = Class.forName(clazz).newInstance(); //根据class生成实例
beans.put(id, o); //将id,以及生成实例,放在map当中
//拿到name之后,把第一个字母大写,前面加上set,来调用set方法,这样,就不用我们写
//userSerivce.setUserDAO(userDAO);这句话了
for(Element propertyElement : (List<Element>)element.getChildren("property")) {
String name = propertyElement.getAttributeValue("name"); //userDAO
String bean = propertyElement.getAttributeValue("bean"); //u
Object beanObject = beans.get(bean);//UserDAOImpl instance
String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
System.out.println("method name = " + methodName);
Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);
m.invoke(o, beanObject); //调用setUserDAO方法
}
}
}catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Object getBean(String name) {
return beans.get(name);
}
}
最核心的内容就是这些,然后我们用Junit4来做测试:
@Test
public void testAdd(){
BeanFactory factory = new ClassPathXMLApplicationContext();
UserService userSerivce = (UserService)factory.getBean("userService"); //拿到userSerivce实例,在实例化该对象的同时,通过它的构造方法,把userDAO注入了
User u = new User();
userSerivce.add(u);
/*虽然我们写的是userSerivce.add(u)这是业务逻辑
实际的处理方式是调用userSerivce.userDAO.add,而userDAO就是我们通过读取配置文件而注入的*/
//控制反转:原来是类自己控制,自己调用自己的setUserDAO,而现在由容器来控制。由容器来生成这个属性。
}
Okay,就是这样了。。Spring乍一看很难理解,但是如果我们看了它的内部原理,其实并不难。
<beans>
<bean id="u" class="com.msb.dao.UserDAOImpl" />
<bean id="userService" class="com.msb.service.UserService" >
<property name="userDAO" bean="u"/>
</bean>
</beans>
这段代码的意图就是先声明一个id为u的bean,再声明一个id为userService的bean,同时,打算把u注入到userService当中,并成为它的userDAO属性。
实现这一环节,就需要一个类来完成这项工作,我们用ClassPathXMLApplicationContext来做。
先写一个接口:
public interface BeanFactory {
public Object getBean(String name);
}
通过这个接口,拿到bean实例
public class ClassPathXMLApplicationContext implements BeanFactory {
private Map<String,Object> beans = new HashMap<String,Object>();
public ClassPathXMLApplicationContext(){ //在构造方法中
SAXBuilder sb=new SAXBuilder();
Document doc;
try {
doc = sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml"));
Element root=doc.getRootElement(); //获取根元素HD
List list=root.getChildren("bean");//找到标签为bean的节点
for(int i=0;i<list.size();i++){ //找到每一个bean
Element element=(Element)list.get(i);
String id=element.getAttributeValue("id"); //拿到它的id
String clazz=element.getAttributeValue("class"); //拿到它的class
Object o = Class.forName(clazz).newInstance(); //根据class生成实例
beans.put(id, o); //将id,以及生成实例,放在map当中
//拿到name之后,把第一个字母大写,前面加上set,来调用set方法,这样,就不用我们写
//userSerivce.setUserDAO(userDAO);这句话了
for(Element propertyElement : (List<Element>)element.getChildren("property")) {
String name = propertyElement.getAttributeValue("name"); //userDAO
String bean = propertyElement.getAttributeValue("bean"); //u
Object beanObject = beans.get(bean);//UserDAOImpl instance
String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
System.out.println("method name = " + methodName);
Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);
m.invoke(o, beanObject); //调用setUserDAO方法
}
}
}catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Object getBean(String name) {
return beans.get(name);
}
}
最核心的内容就是这些,然后我们用Junit4来做测试:
@Test
public void testAdd(){
BeanFactory factory = new ClassPathXMLApplicationContext();
UserService userSerivce = (UserService)factory.getBean("userService"); //拿到userSerivce实例,在实例化该对象的同时,通过它的构造方法,把userDAO注入了
User u = new User();
userSerivce.add(u);
/*虽然我们写的是userSerivce.add(u)这是业务逻辑
实际的处理方式是调用userSerivce.userDAO.add,而userDAO就是我们通过读取配置文件而注入的*/
//控制反转:原来是类自己控制,自己调用自己的setUserDAO,而现在由容器来控制。由容器来生成这个属性。
}
Okay,就是这样了。。Spring乍一看很难理解,但是如果我们看了它的内部原理,其实并不难。
相关文章推荐
- 模拟spring的注入和读取配置文件(ApplicationContext.xml)
- Spring读取xml配置文件的原理与实现
- dom4j实现模拟Spring读取配置文件 注入
- 自定义spring容器--spring容器读取bean配置文件的原理
- 【Spring】Spring的IOC(控制反转)/DI(依赖注入)原理(二):模拟Spring加载配置文件
- 模拟spring的注入和读取配置文件(ApplicationContext.xml)
- SpringBoot内部配置:“application.properties配置”和”使用XML配置”,读取属性文件中的内容,日志配置,Profile配置(学习:SpringBoot实战)
- 模拟Spring注入和读取配置文件信息(支持bean 书写顺序随意)
- Spring读取xml配置文件的原理与实现
- Spring读取xml配置文件的原理与实现
- 用dom4j读取配置文件来模拟spring的bean工厂
- spring-boot读取props和yml配置文件
- spring中如何读取.properties配置文件
- Spring配置文件读取方式
- springboot读取自己定义的配置文件的方式以及使用joda_time来处理时间日期
- ArrayList 与HashSet的比较,及应用反射读取properties配置文件中的数据进行实例化再调用,以及类加载器的使用;还有HashCode的分析,及导致内存泄露,内存溢出的原因之一
- 优化spring的配置文件的配置读取方式
- Spring解析配置文件信息并转换成Spring内部的数据结构
- 【Spring学习04】实例化上下文对象及加载多个配置文件