Spring简单的说就是作为控制反转的容器,看这篇文章前需要先搞懂“控制反转和依赖注入“这个设计模式
我们先来模拟Spring,实现用户添加的功能,新建WEB项目”Spring_0100_AbstractOrientedProgramming“,新建包”com.bjsxt.model“,创建一个User实体
package com.bjsxt.model; public class User { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
新建包”com.bjsxt.dao“,创建操作用户的接口"UserDAO",针对接口编程的好处是,接口的实现类可以无限拓展
package com.bjsxt.dao; import com.bjsxt.model.User; public interface UserDAO { public void save(User user); }
新建包”com.bjsxt.dao.impl“,创建一个接口的实现类”UserDAOImpl“,用一个输出模拟保存成功
package com.bjsxt.dao.impl; import com.bjsxt.dao.UserDAO; import com.bjsxt.model.User; public class UserDAOImpl implements UserDAO { public void save(User user) { //Hibernate //JDBC //XML //NetWork System.out.println("user saved!"); } }
新建包”com.bjsxt.service“,新建类”UserService“,有一个”UserDAO“类型的属性,并且有对应的getter和setter方法,还有一个add方法调用UserDAO的save方法实现用户添加
package com.bjsxt.service; import com.bjsxt.dao.UserDAO; import com.bjsxt.dao.impl.UserDAOImpl; import com.bjsxt.model.User; public class UserService { private UserDAO userDAO; public void add(User user) { userDAO.save(user); } public UserDAO getUserDAO() { return userDAO; } public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } }
按照传统方式,我们应该是在UserService中自己实例化UserDAO属性,但是现在这一切都交给Spring来完成,它会帮我们实例化,并且通过UserServcie的setter方法给UserDAO属性赋值。我们需要将对象写到配置文件里,然后Spring会读取配置文件,在运行时动态生成对象供我们调用
<beans> <bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl" /> <bean id="userService" class="com.bjsxt.service.UserService" > <property name="userDAO" bean="u"/> </bean> </beans>
新建包”com.bjsxt.spring“,创建模拟Spring的接口”BeanFactory“和"ClassPathXmlApplicationContext"
package com.bjsxt.spring; public interface BeanFactory { public Object getBean(String id); }
package com.bjsxt.spring; 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.input.SAXBuilder; public class ClassPathXmlApplicationContext implements BeanFactory { private Map<String , Object> beans = new HashMap<String, Object>(); //IOC Inverse of Control DI Dependency Injection public ClassPathXmlApplicationContext() throws Exception { SAXBuilder sb=new SAXBuilder(); Document doc=sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml")); //�����ĵ����� Element root=doc.getRootElement(); //��ȡ��Ԫ��HD List list=root.getChildren("bean");//ȡ����Ϊdisk������Ԫ�� for(int i=0;i<list.size();i++){ Element element=(Element)list.get(i); String id=element.getAttributeValue("id"); String clazz=element.getAttributeValue("class"); Object o = Class.forName(clazz).newInstance(); System.out.println(id); System.out.println(clazz); beans.put(id, o); for(Element propertyElement : (List<Element>)element.getChildren("property")) { String name = propertyElement.getAttributeValue("name"); //userDAO String bean = propertyElement.getAttributeValue("bean"); //u Object beanObject = beans.get(bean);//UserDAOImpl instance String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1); System.out.println("method name = " + methodName); Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]); m.invoke(o, beanObject); } } } public Object getBean(String id) { return beans.get(id); } }
接下来用JUnit做单元测试,新建源文件夹"Test"存放测试代码,新建包”com.bjsxt.service“,创建测试类”UserServiceTest“
package com.bjsxt.service; import org.junit.Test; import com.bjsxt.dao.UserDAO; import com.bjsxt.model.User; import com.bjsxt.spring.BeanFactory; import com.bjsxt.spring.ClassPathXmlApplicationContext; public class UserServiceTest { @Test public void testAdd() throws Exception { BeanFactory applicationContext = new ClassPathXmlApplicationContext(); UserService service = (UserService)applicationContext.getBean("userService"); User u = new User(); u.setUsername("zhangsan"); u.setPassword("zhangsan"); service.add(u); } }
运行,效果如图
看到了吗,UserService中的add方法需要调用UserDAO的实例方法save,但是并没有实例化UserDAO属性,而是交给了Spring来完成
具体项目文件如图