Spring记录之模拟IoC(三)
2016-05-12 16:59
489 查看
模拟Spring IoC容器 3.0
从xml文件中读取的value值,是String类型,与Java Bean定义的属性,如int,double类型之间如何实现转换呢?上次说过,Apache Commons BeanUtils包,http://commons.apache.org/proper/commons-beanutils/ 该包集成了许多转化器Converter
用它来实现。
步骤一:加jar包
commons-logging-1.2.jar commons-beanutils-1.8.3.jar
步骤二:修改容器实现类
修改值注入的地方package spring.container; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.beanutils.BeanUtils; import spring.config.Bean; import spring.config.Property; import spring.parser.ConfigParser; /** * @author Administrator * */ public class Dom4jClassPathXmlApplicationContext implements BeanFactory { //beans from xml config file private Map<String, Bean> beans; // container to store bean private Map<String, Object> contextMap = new HashMap<String, Object>(); // parse xml file instantly this class is initializing public Dom4jClassPathXmlApplicationContext(String path) { beans = ConfigParser.dom4jParser(path); if (beans != null) { // loop beans for (Entry<String, Bean> en : beans.entrySet()) { String id = en.getKey(); Bean bean = en.getValue(); Object existBean = contextMap.get("id"); // bean is not initialized and scope is singleton if (existBean == null && bean.getScope().equals("singleton")) { // initialize bean. 需检验是否已经注入 // Bean must be checked if it is already been initialized // before this process Object obj = createBean(bean); // put beans into the container contextMap.put(id, obj); } } } } /** * @param bean * @return */ private Object createBean(Bean bean) { String className = null; // user reflection Class clazz = null; try { className = bean.getClassName(); clazz = Class.forName(className); } catch (ClassNotFoundException | NullPointerException e) { e.printStackTrace(); throw new RuntimeException(className + " not found in xml config file."); } // generate Objection Object object = null; try { object = clazz.newInstance(); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); throw new RuntimeException( "no default constructor defined in " + className); } /** * <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> * <property name="driverClassName" value="${jdbc.driverClass}"/> * <property name="url" value="${jdbc.url}"/> * </bean> */ // inject property if (bean.getProperties() != null) { for (Property properties : bean.getProperties()) { String propName = null; Method setterMethod = null; try { propName = properties.getName(); // using setter to inject value <property name="name" // value="changing"/>, <property name="name" ref="ref"/> setterMethod = BeanMethod.getWriterMethod(object,propName); } catch (NullPointerException e) { e.printStackTrace(); throw new RuntimeException("property name is not defined."); } // inject value into object using setter // 这里是值注入,此处通过BeanUtils.populate()方法注入,该方法实现了自动类型转换 if (properties.getValue() != null) { //use apache BeanUtils tool to inject value so that automation of type change can be done Map<String, String[]> paraMap = new HashMap<String, String[]>(); paraMap.put(propName, new String[]{properties.getValue()}); try { BeanUtils.populate(object, paraMap); } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } // inject another Object if (properties.getRef() != null) { // get ref instance Object refBean = contextMap.get(properties.getRef()); // refBean is not generated. Generate it by recursion if (refBean == null) { refBean = createBean(beans.get(properties.getRef())); if(beans.get(properties.getRef()).getScope().equals("singleton")){ // put refBean into Container if scope in the xml file is singleton contextMap.put(properties.getRef(), refBean); } } //setter to inject value or ref try { setterMethod.invoke(object, refBean); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } } return object; } @Override public Object getBean(String id) { Object bean = contextMap.get(id); //if scope is not singleton, then bean does not exist in contextMap and should be null if(bean == null){ bean = createBean(beans.get(id)); } return bean; } }
步骤三:测试
//在Animal类中增加int类型的age属性,设置getter/setter <bean id="animal" class="spring.beans.Animal"> <property name="age" value="150"/> </bean>
@Test public void testBean(){ Dom4jClassPathXmlApplicationContext context = new Dom4jClassPathXmlApplicationContext("/bean.xml"); Animal animal = (Animal)context.getBean("animal"); System.out.println(animal.getAge()); }
结果
相关文章推荐
- Java系统中,使用log4j2,再引入Kafka依赖后,出现log dependency警告的解决
- Java_过滤字符串中非汉子的内容
- java解决几种情况下的中文乱码问题
- java中的System.arraycopy方法
- Spring jdbcTemplate之决不回滚解决方案
- Java基础之编码详解(1)
- springmvc快速浏览入门
- [原创]java WEB学习笔记02:javaWeb开发的目录结构
- 关于Spring整合Quartz,以及对quartz的理解
- Java第六次实验
- MAVEN在eclipse(kepler)里的安装配置
- 【JDK】:HashMap详解
- Java并发编程:剖析ThreadLocal
- 消费者端的Spring JMS 连接ActiveMQ接收生产者Oozie Server发送的Oozie作业执行结果
- java读取properties文件
- 框架 day27 Struts2 入门(概述,基本xml配置,动态方法调用,Action类,ServletAPI访问,结果集)
- Eclipse中安装部署maven插件
- Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)
- Restful形式接口文档生成之Swagger与SpringMVC整合手记
- java变量初始化