引言
从机房收费系统的经典三层架构开始,到七层的设计,最后到ITOO现在的分层思想,每一次的修改都是一次里程碑式的变换。很多书上提倡的重构以及分层的思想,都离不开两句话:前后端分离,前后台分层。
分层思想现在如日中天的就是Spring的出现。我们使用IOC容器,把工厂取代了,减少了代码量,大大的提高了我们的开发效率。
Spring的核心概念有IOC、DI、AOP,我们通过代码来一步一步实现。
IOC(Inversion of Control,控制反转):
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(); // 打印对象类型
}
}
BeanFactory:
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();
}
ClassPathXmlApplicationContext:
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();
}
}
UserDao:
package com.tgb.dao;
import com.tgb.domain.User;
public interface UserDao {
void save(User user);
}
UserDaoImpl:
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()-----");
}
}
domain:
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()-----");
}
}
bean.xml:
<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控制,所以这叫控制反转。