Spring两个重要特性IOC和AOP,本文中简单实现bean的创建以及属性依赖注入。
实现步骤如下:
1、通过dom4j解析bean.xml文件,将bean对象以及依赖属性装入List。
2、遍历list,通过反射机制实例化对象。
3、遍历list,通过反射调用bean里的set方法注入依赖对象以及基本类型属性。
引入dom4j maven依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>myproject</groupId>
<artifactId>myproject</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>myproject Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.8.3</version>
</dependency>
</dependencies>
<build>
<finalName>myproject</finalName>
</build>
</project>
spring bean配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">
<bean id="orderDao" class="com.ocean.spring.bean.OrderDao">
</bean>
<bean id="orderService" class="com.ocean.spring.bean.OrderService">
<!-- 需要注入bean -->
<property name="orderDao" ref="orderDao"/>
<!-- 需要注入基本类型数据 -->
<property name="name" value="ocean"/>
<property name="id" value="56"/>
</bean>
</beans>
package com.ocean.spring.bean;
public class OrderService {
private OrderDao orderDao;
private String name;
private int id;
public void updateOrder() {
System.out.println(this.name+","+this.id);
orderDao.updateOrder();
}
public void setName(String name) {
this.name = name;
}
public void setId(int id) {
this.id = id;
}
// set 方法提供依赖注入
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
}
package com.ocean.spring.bean;
public class OrderDao {
public void updateOrder(){
System.out.println("更新订单信息");
}
}
bean描述类
package com.ocean.spring.bean;
import java.util.ArrayList;
import java.util.List;
/**
* bean描述对象
* @author
*
*/
public class BeanDefine {
private String id;
private String className;
private List<PropertiesDto> propertiesDtos = new ArrayList<PropertiesDto>();
public BeanDefine(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<PropertiesDto> getPropertiesDtos() {
return propertiesDtos;
}
public void setPropertiesDtos(List<PropertiesDto> propertiesDtos) {
this.propertiesDtos = propertiesDtos;
}
}
bean属性描述类
package com.ocean.spring.bean;
/**
* 属性描述对象
*
* @author
*
*/
public class PropertiesDto {
private String name;
private String ref;
private String value;
public PropertiesDto() {
}
public PropertiesDto(String name, String ref, String value) {
this.name = name;
this.ref = ref;
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
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;
}
}
模拟实现bean的实例化以及依赖注入类
package com.ocean.spring.bean;
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.apache.commons.beanutils.ConvertUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
public class SpringIoc {
private List<BeanDefine> beanDefines = new ArrayList<BeanDefine>();
private Map<String, Object> beans = new HashMap<String, Object>();
public static void main(String[] args) {
SpringIoc SpringIoc = new SpringIoc();
SpringIoc.myIoc();
OrderService orderService = (OrderService) SpringIoc.getBeans().get("orderService");
orderService.updateOrder();// 如果报空指针则注入失败,如果打印出信息表示注入成功
}
public void myIoc() {
// dom4j解析xml
readXML("config/spring/spring-bean.xml");
// 利用反射实例化bean
instanceBean();
// bean的属性注入
inject();
}
/**
* dom4j解析xml
*
* @param fileName
*/
private void readXML(String fileName) {
SAXReader saxReader = new SAXReader();
URL url = this.getClass().getClassLoader().getResource(fileName);
try {
Map<String, String> nsMap = new HashMap<String, String>();
nsMap.put("ns", "http://www.springframework.org/schema/beans");
Document document = saxReader.read(url);
XPath xPath = document.createXPath("//ns:beans/ns:bean");// 创建查询路径
xPath.setNamespaceURIs(nsMap);
List<Element> beans = xPath.selectNodes(document);
for (Element element : beans) {
String id = element.attributeValue("id");
String className = element.attributeValue("class");
BeanDefine beanDefine = new BeanDefine(id, className);// bean描述对象
XPath propertysub = element.createXPath("ns:property");
propertysub.setNamespaceURIs(nsMap);
List<Element> properties = propertysub.selectNodes(element);
if (properties != null && properties.size() > 0) {
for (Element property : properties) {
String name = property.attributeValue("name");
String ref = property.attributeValue("ref");
String value = property.attributeValue("value");
if (name != null) {
PropertiesDto propertiesDto = new PropertiesDto();// 属性描述对象
propertiesDto.setName(name);
if (ref != null) {
propertiesDto.setRef(ref);
}
if (value != null) {
propertiesDto.setValue(value);
}
beanDefine.getPropertiesDtos().add(propertiesDto);
}
}
}
beanDefines.add(beanDefine);
}
} catch (DocumentException e) {
}
}
/**
* 实例化
*/
private void instanceBean() {
if (beanDefines == null || beanDefines.size() == 0) {
System.out.println("容器中没有需要实例化的bean");
return;
}
try {
for (BeanDefine beanDefine : beanDefines) {
beans.put(beanDefine.getId(), Class.forName(beanDefine.getClassName()).newInstance());
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 依赖注入
*/
private void inject() {
try {
for (BeanDefine beanDefine : beanDefines) {
List<PropertiesDto> propertiesDtos = beanDefine.getPropertiesDtos();
if (propertiesDtos != null && propertiesDtos.size() > 0) {
Object bean = beans.get(beanDefine.getId());
PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(bean.getClass())
.getPropertyDescriptors();
for (PropertiesDto propertiesDto : propertiesDtos) {
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
if (propertyDescriptor.getName().equals(propertiesDto.getName())) {
Method setter = propertyDescriptor.getWriteMethod();// 获取属性的set方法
if (propertiesDto.getRef() != null && !"".equals(propertiesDto.getRef())) {
setter.invoke(bean, beans.get(propertiesDto.getRef()));// 将依赖的bean注入进来
}
String value = propertiesDto.getValue();
if (value != null && !"".equals(value)) {
// 用apache的ConvertUtils将基本类型属性注入进来
setter.invoke(bean,
ConvertUtils.convert(value, propertyDescriptor.getPropertyType()));
}
break;
}
}
}
}
}
} catch (Exception e) {
}
}
public Map<String, Object> getBeans() {
return beans;
}
}
工程目录结构图