1、概述
Spring容器的原理就是基于解析XML文件、反射创建Bean、通过工厂模式管理Bean集合, 只需要调用getBean("beanID")方法即可获得这Bean。
2、实现过程
2.1 反射机制
反射.png详情
2.2 XML解析
XML文件示例:
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="user" class="com.falcon.model.User" />
<bean id="userDAO" class="com.falcon.dao.impl.UserDAOImpl" />
<bean id="userService" class="com.falcon.service.UserService">
<property name="userDAO" bean="userDAO" />
</bean>
</beans>
ClassPathXmlApplicationContext:读取xml文件内容,并创建对象及对象关系(使用setter方式)
package com.falcon.spring;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
public class ClassPathXmlApplicationContext implements BeanFactory
{
private Map<String, Object> beans = new HashMap<String, Object>();
public ClassPathXmlApplicationContext() throws JDOMException, IOException,
InstantiationException, IllegalAccessException,
ClassNotFoundException, SecurityException, NoSuchMethodException,
IllegalArgumentException, InvocationTargetException
{
SAXBuilder sb = new SAXBuilder();
// 构造文档对象
Document doc = sb.build(ClassPathXmlApplicationContext.class
.getClassLoader().getResourceAsStream("beans.xml"));
// 获取根元素
Element root = doc.getRootElement();
// 取到根元素所有元素
List list = root.getChildren();
for (int i = 0; i < list.size(); i++)
{
Element element = (Element) list.get(i);
// 取id子元素
String beanid = element.getAttributeValue("id");
// 取class子元素
String clzss = element.getAttributeValue("class");
// 实例化
Object o = Class.forName(clzss).newInstance();
// 将所有bean放入map中
beans.put(beanid, o);
// 获取property 进行依赖注入
for (Element propertyElement : (List<Element>) element
.getChildren("property"))
{
String name = propertyElement.getAttributeValue("name");
System.out.println(name);//userDAO
String bean = propertyElement.getAttributeValue("bean");
System.out.println(bean);//userDAO
// 从beans.xml中根据id取到类的对象
//Object beanObj = this.getBean(name);
// 从beans.xml中根据id取到类的对象
Object beanObj = this.getBean(bean);
System.out.println(beanObj);//com.yyb.dao.impl.UserDAOImpl@a09ee92
// 形成setXXX方法名
String methodName = "set" + name.substring(0, 1).toUpperCase()
+ name.substring(1);
System.out.println(name.substring(0, 1).toUpperCase());//U
System.out.println(name.substring(1));//serDAO
System.out.println(methodName);//setUserDAO
// 反射机制对方法进行调用,将对象在加载bean时就注入到环境上下文中
Method m = o.getClass().getMethod(methodName,
beanObj.getClass().getInterfaces()[0]);
System.out.println(o.getClass());//class com.yyb.service.UserService
System.out.println(beanObj.getClass().getInterfaces()[0]);//interface com.yyb.dao.UserDAO
System.out.println(m);//public void com.yyb.service.UserService.setUserDAO(com.yyb.dao.UserDAO)
// 执行注入,相当于执行了一个setXXX(args..)的方法
m.invoke(o, beanObj);
}
}
}
@Override
public Object getBean(String name)
{
return beans.get(name);
}
}
2.3 BeanFactory
接口示例:
public interface BeanFactory {
Object getBean(String name);
}
Bean示例:
public class User {
private String userName;
private String password;
/**
* @return the userName
*/
public String getUserName()
{
return userName;
}
/**
* @param userName
* the userName to set
*/
public void setUserName(String userName)
{
this.userName = userName;
}
/**
* @return the password
*/
public String getPassword()
{
return password;
}
/**
* @param password
* the password to set
*/
public void setPassword(String password)
{
this.password = password;
}
public String toString()
{
StringBuffer sb = new StringBuffer();
sb.append(this.userName);
sb.append(this.password);
return sb.toString();
}
}
public interface UserDAO {
void save(User u);
void delete();
}
public class UserDAOImpl implements UserDAO {
@Override
public void save(User u) {
System.out.println("User:" + u.toString());
}
@Override
public void delete() {
System.out.println("delete User");
}
}
public class UserService {
private UserDAO userDAO;
public void addUser(User u)
{
this.userDAO.save(u);
}
/**
* @return the userDAO
*/
public UserDAO getUserDAO()
{
return userDAO;
}
/**
* @param userDAO
* the userDAO to set
*/
public void setUserDAO(UserDAO userDAO)
{
this.userDAO = userDAO;
}
}
2.4 自动依赖注入
依赖注入核心部分
// 实例化
Object o = Class.forName(clzss).newInstance();
// 将所有bean放入map中
beans.put(beanid, o);
// 获取property 进行依赖注入
for (Element propertyElement : (List<Element>) element
.getChildren("property"))
{
String name = propertyElement.getAttributeValue("name");
System.out.println(name);//userDAO
String bean = propertyElement.getAttributeValue("bean");
System.out.println(bean);//userDAO
// 从beans.xml中根据id取到类的对象
//Object beanObj = this.getBean(name);
// 从beans.xml中根据id取到类的对象
Object beanObj = this.getBean(bean);
System.out.println(beanObj);//com.yyb.dao.impl.UserDAOImpl@a09ee92
// 形成setXXX方法名
String methodName = "set" + name.substring(0, 1).toUpperCase()
+ name.substring(1);
System.out.println(name.substring(0, 1).toUpperCase());//U
System.out.println(name.substring(1));//serDAO
System.out.println(methodName);//setUserDAO
// 反射机制对方法进行调用,将对象在加载bean时就注入到环境上下文中
Method m = o.getClass().getMethod(methodName,
beanObj.getClass().getInterfaces()[0]);
System.out.println(o.getClass());//class com.yyb.service.UserService
System.out.println(beanObj.getClass().getInterfaces()[0]);//interface com.yyb.dao.UserDAO
System.out.println(m);//public void com.yyb.service.UserService.setUserDAO(com.yyb.dao.UserDAO)
// 执行注入,相当于执行了一个setXXX(args..)的方法
m.invoke(o, beanObj);
}
实现效果:
Service service=(Service)beans.get("userService");
Dao dao = (Dao)beans.get("userDAO");
//依赖注入,Service实现依赖dao的实现
service.setDao(dao);
3、测试
public class client {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException, JDOMException, IOException {
BeanFactory factory = new ClassPathXmlApplicationContext();
//通过工厂直接获取
UserService userService = (UserService) factory.getBean("userService");
//其实User也可以从工厂中获得
User u=(User)factory.getBean("user");
//User u = new User();
u.setUserName("yyb");
u.setPassword("1234");
userService.addUser(u);//打印结果yyb1234
}
}
网友评论