Spring IOC的容易实现(附demo)

Spring IOC的简单实现(附demo)


简单的说,Spring就是通过工厂+反射将我们的bean放到它的容器中的,当我们想用某个bean的时候,只需要调用getBean("beanID")方法即可

 

原理简单说明:

 

Spring容器的原理,其实就是通过解析xml文件,通过反射创建出我们所需要的bean将这些bean挨个放到集合中,然后对外提供一个getBean()方法,以便我们获得这bean

 

下面我们来简单实现一个demo

 

beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>  
    <bean id="user" class="com.yyb.model.User" />  
    <bean id="userDAO" class="com.yyb.dao.impl.UserDAOImpl" />  
    <bean id="userService" class="com.yyb.service.UserService">  
        <property name="userDAO" bean="userDAO" />  
    </bean>  
</beans> 

BeanFactory

public interface BeanFactory {

	 Object getBean(String name);  
}

ClassPathXmlApplicationContext:读取xml文件内容,并创建对象及对象关系(使用setter方式)

package com.yyb.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);
	}
}

对于以上这段代码实现的效果为:

 

Service service=(Service)beans.get("userService");

Daodao = (Dao)beans.get("userDAO");

//依赖注入,Service实现依赖dao的实现

service.setDao(dao);

 

User:实体类

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();  
    }  
}

UserDAO

public interface UserDAO {
	 void save(User u);  
	 void delete(); 
}

UserDAOImpl

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");  
	          
	    }  
}

UserService

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;  
    }  
}

下面我们来简单测试一下实现的效果:


Client

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
	}

}


当然以上我们是通过setter方法注入,还可以使用构造器注入,也就是在建立对象的时候建立关系(即在UserService的构造函数中添加对userDAO的赋值操作

 

总结:

 

以上通过IOC的一个简要实现实例,模拟了Spring中IOC的实现,虽然只是完成了Spring中依赖注入的一小部分工作,但是很好的展现了Java反射机制在Spring中的应用,能使我们能更好的从原理上了解IOC的实现,也能为我们实现自己的Spring框架提供方案