博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
自定义ClassPathXMLApplication实现spring容器ioc功能
阅读量:94 次
发布时间:2019-02-26

本文共 5686 字,大约阅读时间需要 18 分钟。

看传智播客spring原理讲解的视频整理而来,当时是2011年,时隔8年,在网上找到了一些代码,然后自己整理了一下,基本能够拼装出来。spring容器ioc的实现,无非就是通过反射获取bean实例,然后实例化,当bean实例属性中包含其他bean,那么也是根据反射来注入实例。基本思路就是解析xml文件,然后通过反射机制找到bean,实例化,最后根据属性ref来注入依赖。

这里无需引入spring相关的jar包,但是我们需要引入一个spring的配置文件。配置文件的内容如下:

在自定义MyClassPathXMLApplication之前,我们需要把xml配置文件中的UserDaoImpl.java和UserService.java类文件给出来。

UserDao.java

package com.xxx.spring.dao;public interface UserDao {	public void say(String name);}

UserDaoImpl.java 

package com.xxx.spring.dao;public class UserDaoImpl implements UserDao {	@Override	public void say(String name) {		System.out.println("Hello,"+name);	}}

UserService.java

package com.xxx.spring.service;import com.xxx.spring.dao.UserDao;public class UserService {	private UserDao userDao;	public UserDao getUserDao() {		return userDao;	}	public void setUserDao(UserDao userDao) {		this.userDao = userDao;	}		public void say(String name){		userDao.say(name);	}}

为了解析xml和装配bean实例,我们自定义两个实体。

BeanDefinition.java 这里对应xml配置文件中的实体bean配置:

<bean id="xxx" class="com.xxx.dao.XXX"><property name="yyy" ref="zzz"/></bean>

package com.xxx.spring;import java.util.ArrayList;import java.util.List;public class BeanDefinition {	private String id;	private String className;		private List
properties = new ArrayList
(); public BeanDefinition(String id, String className) { this.id = id; this.className = className; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public List
getProperties() { return properties; } public void setProperties(List
properties) { this.properties = properties; } }

PropertyDefinition.java 这里对应xml配置文件中的属性配置:<property name="yyy" ref="zzz"/>

package com.xxx.spring;public class PropertyDefinition {	private String name;	private String ref;		public PropertyDefinition(String name,String ref){		this.name = name;		this.ref = ref;	}	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}	public String getRef() {		return ref;	}	public void setRef(String ref) {		this.ref = ref;	}		}

接下来就是最重要的自定义解析类:MyClassPathXMLApplication.java

package com.xxx.spring;import java.beans.Introspector;import java.beans.PropertyDescriptor;import java.lang.reflect.Method;import java.net.URL;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import org.dom4j.Document;import org.dom4j.Element;import org.dom4j.XPath;import org.dom4j.io.SAXReader;import com.xxx.spring.service.UserService;public class MyClassPathXMLApplication {		//存放自定义BeanDefinition实例	private List
beans = new ArrayList
(); //存放通过反射构建的bean实例 private Map
singletons = new HashMap
(); public MyClassPathXMLApplication(String fileName){ this.readXML(fileName); this.instanceBeans(); this.injectObject(); } /** * 解析xml文件 * @param fileName */ @SuppressWarnings("unchecked") public void readXML(String fileName){ SAXReader reader = new SAXReader(); Document document = null; try { URL xmlpath = this.getClass().getClassLoader().getResource(fileName); document = reader.read(xmlpath); Map
nsMap = new HashMap
(); nsMap.put("ns", "http://www.springframework.org/schema/beans"); XPath xpath = document.createXPath("//ns:beans/ns:bean"); xpath.setNamespaceURIs(nsMap); List
beanDefines = xpath.selectNodes(document); for(Element ele:beanDefines){ String id = ele.attributeValue("id"); String className = ele.attributeValue("class"); BeanDefinition beanDefinition = new BeanDefinition(id, className); XPath propPath = document.createXPath("ns:property"); propPath.setNamespaceURIs(nsMap); List
props = propPath.selectNodes(ele); for(Element prop:props){ String name = prop.attributeValue("name"); String ref = prop.attributeValue("ref"); PropertyDefinition propertyDefinition = new PropertyDefinition(name, ref); beanDefinition.getProperties().add(propertyDefinition); } System.out.println(id+"==>"+className); beans.add(beanDefinition); } } catch (Exception e) { } } /** * 实例化bean对象 */ public void instanceBeans(){ for(BeanDefinition bean:beans){ try { if(bean.getClassName() != null && !"".equals(bean.getClassName().trim())){ singletons.put(bean.getId(), Class.forName(bean.getClassName()).newInstance()); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } } /** * 为对象属性注入值 */ public void injectObject(){ //bean userDao //bean userService for(BeanDefinition bean:beans){ //com.xxx.spring.dao.UserDao //com.xxx.spring.service.UserService Object object = singletons.get(bean.getId()); if(object != null){ try{ PropertyDescriptor[] pds = Introspector.getBeanInfo(object.getClass()).getPropertyDescriptors(); for(PropertyDefinition propertyDefinition:bean.getProperties()){ for(PropertyDescriptor pd:pds){ if(propertyDefinition.getName().equals(pd.getName())){ Method setter = pd.getWriteMethod(); if(setter != null){ Object value = singletons.get(propertyDefinition.getRef()); setter.setAccessible(true); setter.invoke(object, value);//userService.setUserDao(userDao); } break; } } } }catch(Exception e){ e.printStackTrace(); } } } } public Object getBean(String beanName){ return singletons.get(beanName); } public static void main(String[] args) { MyClassPathXMLApplication application = new MyClassPathXMLApplication("spring.xml"); UserService service = (UserService)application.getBean("userService"); service.say("spring."); }}

这个类承担了ioc功能的主要职责,负责解析xml文件,实例化bean实体,根据属性名注入依赖。 

这里运行的结果如下所示:

转载地址:http://wuey.baihongyu.com/

你可能感兴趣的文章