[转帖]  利用Java反射机制模拟Spring的DI注入_Tomcat, WebLogic及J2EE讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Tomcat, WebLogic及J2EE讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 4865 | 回复: 0   主题: [转帖]  利用Java反射机制模拟Spring的DI注入        下一篇 
522080330
注册用户
等级:少校
经验:1478
发帖:79
精华:20
注册:2013-1-18
状态:离线
发送短消息息给522080330 加好友    发送短消息息给522080330 发消息
发表于: IP:您无权察看 2013-1-24 14:04:20 | [全部帖] [楼主帖] 楼主

    模拟了spring容器的依赖注入,其实spring内部也是通过反射机制来实现的控制反转。主要是看下spring包下的ClassPathXmlApplicationContext类的实现。

完整代码如下:

package com.bjsxt.model;
public class User {
      private String name;
      public String getName() {
            return name;
      }
      public void setName(String name) {
            this.name = name;
      }
}
package com.bjsxt.dao;
import com.bjsxt.model.User;
//设计这个接口,是为了更灵活,因此不同的数据库产品,实现方式不一样
//为了可扩展,把这里设计成接口
public interface UserDao {
      public void save(User u);
}
package com.bjsxt.dao.impl;
import com.bjsxt.dao.UserDao;
import com.bjsxt.model.User;
public class UserDaoImpl implements UserDao {
      public void save(User u) {
            System.out.println("a user is save.");
      }
}
package com.bjsxt.service;
import com.bjsxt.dao.UserDao;
import com.bjsxt.model.User;
public class UserService {
      //这里我定义成接口类型,这样,我想用哪种数据库产品的实现
      //我就new哪种,比如userDao = new UserDaoImpl(),如果我想换
      //其它的实现,就更改下那句话就行,要是放在配置文件里,就只需更改配置文件
      //这就是面向接口的编程
      private UserDao userDao;
      public UserDao getUserDao() {
            return userDao;
      }
      public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
      }
      public void save(User u){
            userDao.save(u);
      }
}
package spring;
public interface BeanFactory {
      Object getBean(String id);
}
package spring;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import com.bjsxt.dao.UserDao;
public class ClassPathXmlApplicationContext implements BeanFactory{
      private Map<String,Object> beans = new HashMap<String,Object>();
      public ClassPathXmlApplicationContext() throws JDOMException, IOException{
            SAXBuilder sb = new SAXBuilder();
            Document doc = sb.build(ClassPathXmlApplicationContext.class
            .getClassLoader().getResourceAsStream("beans.xml"));
            Element root = doc.getRootElement();
            List list = root.getChildren("bean");
            for(int i=0;i<list.size();i++){
                  Element element = (Element) list.get(i);
                  String id = element.getAttributeValue("id");
                  String clazz = element.getAttributeValue("class");
                  Object o = null;
                  try {
                        //利用反射机制,根据完整的包名+类名,new出实例
                        o = Class.forName(clazz).newInstance();
                        beans.put(id, o);
                  } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                  } catch (InstantiationException e) {
                        e.printStackTrace();
                  } catch (IllegalAccessException e) {
                        e.printStackTrace();
                  }
                  List elements = element.getChildren("property");
                  for(int j=0;j<elements.size();j++){
                        Element ele = (Element) elements.get(j);
                        String name = ele.getAttributeValue("name");//userDao
                        String bean = ele.getAttributeValue("bean");//u
                        Object beanObject = beans.get(bean);//userDaoImpl instance
                        //其实就相当于找方法名setUserDao;
                        String methodName = "set"+name.substring(0,1).toUpperCase()+name.substring(1);
                        try {
                              //根据反射机制,执行set方法,这里,先找到方法名,
                              //根据方法名和方法参数拿到method
                              // 比如,public void setUserDao(UserDao userDao),这里的方法参数userDao它实现了
                              //一个接口,所以数组下标为0,所以
                              //这样就完成了注入
                              Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);
                              m.invoke(o, beanObject);
                        } catch (SecurityException e) {
                              e.printStackTrace();
                        } catch (NoSuchMethodException e) {
                              e.printStackTrace();
                        } catch (IllegalArgumentException e) {
                              e.printStackTrace();
                        } catch (IllegalAccessException e) {
                              e.printStackTrace();
                        } catch (InvocationTargetException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                        }
                  }
            }
      }
      public Object getBean(String id) {
            return beans.get(id);
      }
}
beans.xml
<beans>
<bean id="u" class="com.bjsxt.dao.impl.UserDaoImpl" />
<bean id="userService" class="com.bjsxt.service.UserService" >
<property name="userDao" bean="u"/>
</bean>
</beans>


测试代码如下:

package com.bjsxt.service;
import static org.junit.Assert.*;
import java.io.IOException;
import org.jdom.JDOMException;
import org.junit.Test;
import spring.ClassPathXmlApplicationContext;
import com.bjsxt.model.User;
public class UserServiceTest {
      //junit4的特点就是不用显示继承TestCase,只要在那个方法前加上注解@Test
      public void testSave() {
            ClassPathXmlApplicationContext context = null;
            try {
                  context = new ClassPathXmlApplicationContext();
            } catch (JDOMException e) {
                  e.printStackTrace();
            } catch (IOException e) {
                  e.printStackTrace();
            }
            UserService us = (UserService) context.getBean("userService");
            User u = new User();
            us.save(u);
      }
}




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论