从机房收费系统的经典三层架构开始,到七层的设计,最后到ITOO现在的分层思想,每一次的修改都是一次里程碑式的变换。很多书上提倡的重构以及分层的思想,都离不开两句话:前后端分离,前后台分层。
分层思想现在如日中天的就是Spring的出现。我们使用IOC容器,把工厂取代了,减少了代码量,大大的提高了我们的开发效率。
Spring的核心概念有IOC、DI、AOP,我们通过代码来一步一步实现。
spring架构核心的概念没有这么复杂。我们都知道:Java程序中每个业务逻辑至少需要两个或以上的对象来写作完成,同城,每个对象在使用他的合作对象时,自己都要new一个对象这样的语法来完成合作对象的申请工作,这样耦合度太高了,所以,我们为了降低耦合,我们使用了继承,后来因为需要应对更多的变化,我们使用了工厂,最后,工厂的代码太多,我们就是用了Spring容器。IOC的思想是:Spring容器本来实现这些相互依赖对象的创建、协调工作。对象值需要关心业务逻辑本身就可以了。从这方面来讲,对象如何得到他的协作独享的责任被翻转了(IOC、DI)。
IOC用一句话总结:动态的向某个对象提供它所需要的其他对象。
IOC的实现,是配置文件+反射。
目录结构:
引入两个包:cglib-nodep-2.jar和jdom.jar。
这里从上到下Clint:
package com.tgb.client; import com.tgb.config.BeanFactory; import com.tgb.config.ClassPathXmlApplicationContext; import com.tgb.dao.UserDao; import com.tgb.daoImpl.UserDaoImpl; import com.tgb.domain.User; import com.tgb.service.UserService; /** * 测试容器增加对象 * @ClassName: client * @Description: TODO(这里用一句话描述这个类的作用) * @author qmx * @date 2016年5月28日 * */ public class ContainTest { public static void main(String[] args) throws Exception { //初始化容器对象 BeanFactory factory = new ClassPathXmlApplicationContext(); User user = new User(); //获取容器中 UserDao对象 Object proxyObject = factory.getBean("UserDao"); UserDao userDao = (UserDao) proxyObject; UserDao userDao2 = new UserDaoImpl(); factory.put("userDao2", userDao2); for (int i = 0; i < 20; i++) { //添加对象在容器中 factory.put("user" + i, new User()); } //打印容器中对象个数 factory.printAllbeanId(); System.out.println("-------------"); factory.printTypeName(); // 打印对象类型 } }
package com.tgb.config; import java.util.List; import java.util.Map; /** * /@ClassName: ContainerBeans * @Description: 容器接口,提供容器公共服务方法, 增加,删除,遍历,获取对象,遍历类型,容器大小等方法 * /@author qmx */ public interface BeanFactory { /** * 获取容器中指定对象 * * @param id * 对象名称如: getBean("user") * @return */ public Object getBean(String id); /** * 容器中放入对象 * * @param k * @param v * @return */ public Object put(String k, Object v); /** * 打印容器中所有对象类型 */ public void printTypeName(); /** * 获取容器中所有对象 返回类型 Map<string(对象类型),Object(对象)> * * @return Map<string(对象类型),Object(对象)> */ public Map<String, Object> getAllBean(); /** * 获取容器所有bean */ public void printAllbeanId(); public void remove(String id); /** * 容器中对象的数量 * @return */ public int size(); }
package com.tgb.config; import java.lang.reflect.Method; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; import org.jdom.Document; import org.jdom.Element; import org.jdom.input.SAXBuilder; /*@ClassName: ContainerBeans * @Description: 容器接口,提供容器公共服务方法, 增加,删除,遍历,获取对象,遍历类型,容器大小等方法 * @author [hanyk] **/ public class ClassPathXmlApplicationContext implements BeanFactory { // 对象集合(包含服务类,关系类和业务类) private Map<String, Object> beans = new HashMap<String, Object>(); // 是否启用aop private boolean isAop = true; public ClassPathXmlApplicationContext() throws Exception { SAXBuilder sb = new SAXBuilder(); // 读取xml为doc文档 Document doc = sb.build(Thread.currentThread().getContextClassLoader() .getResourceAsStream("beans.xml")); Element root = doc.getRootElement(); Element aopElement = (Element) root.getChildren("aop").get(0); // 获取aop标签 isAop = Boolean.parseBoolean(aopElement.getAttributeValue("isaop")); // 获取bean标签为list List list = root.getChildren("bean"); List aopBeforeList = root.getChildren("aspectbefore");// 前置增强 List aopAfterList = root.getChildren("aspectafter"); if (aopBeforeList != null) { beans.put("aspectbefore", aopBeforeList); } if (aopAfterList != null) { beans.put("aspectafter", aopAfterList); } // 读取bean 标签,逐项实例化为具体对象 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(); beans.put(id, o); // for循环判断将依赖项逐项实例化,进行set注入 for (Element propertyElement : (List<Element>) element .getChildren("property")) { String name = propertyElement.getAttributeValue("name"); // userDAO String bean = propertyElement.getAttributeValue("ref"); // u Object beanObject = beans.get(bean);// UserDAOImpl instance // 获取对象属性,set方法 String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1); // 获取具体method方法 Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]); // 调用该方法 m.invoke(o, beanObject); } } } /** * 获取容器中指定对象 * * @param id * 对象名称如: getBean("user") * @return */ public Object getBean(String id) { return beans.get(id); } /** * 容器中放入对象 * * @param k * @param v * @return */ public Object put(String k, Object v) { return beans.put(k, v); } /** * 打印容器中所有对象类型 */ public void printTypeName() { Set<String> hashSet = new HashSet<String>(); Set<Entry<String, Object>> entryset = beans.entrySet(); { Iterator iterator = entryset.iterator(); while (iterator.hasNext()) { Entry<String, Object> entry = (Entry<String, Object>) iterator .next(); hashSet.add(entry.getValue().getClass().getSimpleName()); } } for (String setType : hashSet) { System.out.println(setType); } } /** * 获取容器中所有对象 * * @return Map<string(对象类型),Object(对象)> */ public Map<String, Object> getAllBean() { Map<String, Object> beanList = new HashMap<String, Object>(); Iterator iterator = beans.entrySet().iterator(); while (iterator.hasNext()) { Entry<String, Object> entry = (Entry<String, Object>) iterator .next(); beanList.put(entry.getValue().getClass().getSimpleName(), entry.getValue()); } return beanList; } /*** * 删除指定对象 */ public void remove(String id) { beans.remove(id); } /*** * 打印所有注入对象 */ public void printAllbeanId() { Set<Entry<String, Object>> entryset = beans.entrySet(); Set<String> linkSet = new TreeSet<String>(); { Iterator iterator = entryset.iterator(); while (iterator.hasNext()) { Entry<String, Object> entry = (Entry<String, Object>) iterator .next(); linkSet.add(entry.getKey()); // System.out.println(entry.getKey()); } System.out.println(linkSet.toString()); System.out.println("容器中的对象个数是" + size() + "个"); } } /** * 获取容器中对象的个数 */ public int size() { return beans.size(); } }
package com.tgb.dao; import com.tgb.domain.User; public interface UserDao { void save(User user); }
package com.tgb.daoImpl; import com.tgb.dao.UserDao; import com.tgb.domain.User; public class UserDaoImpl implements UserDao { @Override public void save(User user) { System.out.println("-----userDao.save()-----"); } }
package com.tgb.domain; 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; } }
package com.tgb.service; import com.tgb.dao.UserDao; import com.tgb.daoImpl.UserDaoImpl; import com.tgb.domain.User; public class UserService { private UserDao userDao; public UserDao getUserDao() { return userDao; } public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void addUser(User user) { userDao.save(user); System.out.println("----UserService.add()-----"); } }
<beans> <!-- 对象配置文件 --> <bean id="UserDao" class="com.tgb.daoImpl.UserDaoImpl" /> <bean id="userService" class="com.tgb.service.UserService"> <property name="userDao" ref="UserDao" /> </bean> <aop isaop="true"></aop> </beans>
[UserDao, aspectafter, aspectbefore, user0, user1, user10, user11, user12, user13, user14, user15, user16, user17, user18, user19, user2, user3, user4, user5, user6, user7, user8, user9, userDao2, userService] 容器中的对象个数是25个 ------------- User UserService UserDaoImpl FilterList
简单来讲,Spring所提倡的开发方式就是,所有的类都会在Sprig容器中登记,告诉Spring你是什么,你需要什么东西,然后Spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。
所有的类的创建、销毁都有spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。