Spring实现IOC容器

引言


从机房收费系统的经典三层架构开始,到七层的设计,最后到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;
	}		
}


UserService:


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控制,所以这叫控制反转。

你可能感兴趣的:(spring,IOC)