Spring 实现IOC容器(二)
2016-05-30 21:41
465 查看
连载2,:Spring中实现IOC容器,应用动态代理。
结构目录:
我们同样从上到下写:
ContainTest:
package com.tgb.client;
import com.tgb.config.BeanFactory;
import com.tgb.config.ClassPathXmlApplicationContext;
import com.tgb.dao.UserDao;
import com.tgb.domain.User;
/**
* 测试容器AOP效果
* @ClassName: ContainTest
* @Description:
* @author qmx
* @date 2016年5月30日
*
*/
public class ContainTest {
public static void main(String[] args) throws Exception {
//初始化容器对象
BeanFactory factory = new ClassPathXmlApplicationContext();
User user = new User();
user.setUserName("hanyankun");
//获取容器中userDao对象
UserDao userDao = (UserDao) factory.getBean("UserDao");
System.out.println("-----测试一");
userDao.save(user);
}
}
AspectBean:
package com.tgb.config;
/***
*
* 日志对象
*/
public class AspectBean {
public void before(Object proxy) {
System.out.println("---Before1-日志----");
}
public static void after(Object proxy) {
System.out.println("---After1-日志---");
}
public void save(Object proxy) {
System.out.println("---Save1-日志--");
}
}
AspectBean2:
package com.tgb.config;
/**
* 事务对象
* @ClassName: AspectBean2
* @Description: TODO(这里用一句话描述这个类的作用)
* @author
* @date
*
*/
public class AspectBean2 {
public void before(Object proxy) {
System.out.println("---Before2-事务--");
}
public static void after(Object proxy) {
System.out.println("---After2-事务--");
}
public void save(Object proxy){
System.out.println("---Save2-事务--");
}
}
BeanFactory:
package com.tgb.config;
import java.util.List;
import java.util.Map;
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();
}
ClassPathXmlApplication:
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
**/
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) {
if (!isAop) {
return beans.get(id);
}
return new JDKDynamicProxy(beans.get(id),beans).getProxy();
}
/**
* 容器中放入对象
*
* @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();
}
}
JDKDynamicProxy:
package com.tgb.config;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Map;
import org.jdom.Element;
/***
* ClassName: JDKDynamicProxy
* @Description: AOP实现对业务容器 的增强,对业务容器中每个对象增强 服务类中的方法,根据 关系容器配置,
* 实现特性方法增强
* @author qmx
*
*/
public class JDKDynamicProxy implements InvocationHandler {
private Object target;//被代理类
//对象集合(包含服务类,关系类和业务类)
private Map<String, Object> aspectObject;
public JDKDynamicProxy(Object target, Map<String, Object> aspectMap) {
this.target = target;
this.aspectObject = aspectMap;
}
//获取代理对象
@SuppressWarnings("unchecked")
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target
.getClass().getInterfaces(), this);
}
//回调对象,根据传入对象调用代理类方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//获取对象关系
List beforeList = (List) aspectObject.get("aspectbefore");
//回调服务对象方法
invokeAspectName(beforeList, method, args);
//回调代理对象方法
Object result = method.invoke(target, args);
return result;
}
/**
* 拦截方法匹配
*
* @param beforeList
* 拦截器的所有对象
* @param method
* @param args
* @throws NoSuchMethodException
* @throws SecurityException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
*/
public void invokeAspectName(List beforeList, Method method, Object[] args)
throws NoSuchMethodException, SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
if (beforeList != null) {
for (int i = 0; i < beforeList.size(); i++) {
Element element = (Element) beforeList.get(i);
String aspectClass = element.getAttributeValue("ref");// 获取容器中切入类名称
String aspectName = element.getAttributeValue("aspectMethod");// 执行的切入方法
Class clazz = aspectObject.get(aspectClass).getClass(); // 获取切入类
String elementMethod = element.getAttributeValue("method");// 获取被切入类方法
if (aspectName == null) {
Method[] methods = clazz.getMethods();
for (int j = 0; j < methods.length; j++) {
System.out.println("获取全部公共方法的方法:" + methods[j].toString());
}
} else {
if (method.getName().equals(elementMethod)) {
Method jinectmethod = clazz.getMethod(aspectName, Object.class); // 反射调用切入类方法
jinectmethod.invoke(aspectObject.get(aspectClass), args);
}
}
}
}
}
}
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( this.getClass()+"-----userDao.save()-----");
}
}
User:
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>
<!-- 服务类 -->
<bean id="aspectBean" class="com.tgb.config.AspectBean"></bean>
<bean id="aspectBean2" class="com.tgb.config.AspectBean2"></bean>
<aop isaop="true"></aop>
<!-- 关系配置(业务与服务配置) -->
<aspectbefore ref="aspectBean" method="save" aspectMethod="save"></aspectbefore>
<aspectbefore ref="aspectBean2" method="before" aspectMethod="after"></aspectbefore>
<aspectafter ref="aspectBean" method="after" aspectMethod="before"></aspectafter>
</beans>
运行之后的效果为:
-----测试一
---Save1-日志--
class com.tgb.daoImpl.UserDaoImpl-----userDao.save()-----
结构目录:
我们同样从上到下写:
ContainTest:
package com.tgb.client;
import com.tgb.config.BeanFactory;
import com.tgb.config.ClassPathXmlApplicationContext;
import com.tgb.dao.UserDao;
import com.tgb.domain.User;
/**
* 测试容器AOP效果
* @ClassName: ContainTest
* @Description:
* @author qmx
* @date 2016年5月30日
*
*/
public class ContainTest {
public static void main(String[] args) throws Exception {
//初始化容器对象
BeanFactory factory = new ClassPathXmlApplicationContext();
User user = new User();
user.setUserName("hanyankun");
//获取容器中userDao对象
UserDao userDao = (UserDao) factory.getBean("UserDao");
System.out.println("-----测试一");
userDao.save(user);
}
}
AspectBean:
package com.tgb.config;
/***
*
* 日志对象
*/
public class AspectBean {
public void before(Object proxy) {
System.out.println("---Before1-日志----");
}
public static void after(Object proxy) {
System.out.println("---After1-日志---");
}
public void save(Object proxy) {
System.out.println("---Save1-日志--");
}
}
AspectBean2:
package com.tgb.config;
/**
* 事务对象
* @ClassName: AspectBean2
* @Description: TODO(这里用一句话描述这个类的作用)
* @author
* @date
*
*/
public class AspectBean2 {
public void before(Object proxy) {
System.out.println("---Before2-事务--");
}
public static void after(Object proxy) {
System.out.println("---After2-事务--");
}
public void save(Object proxy){
System.out.println("---Save2-事务--");
}
}
BeanFactory:
package com.tgb.config;
import java.util.List;
import java.util.Map;
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();
}
ClassPathXmlApplication:
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
**/
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) {
if (!isAop) {
return beans.get(id);
}
return new JDKDynamicProxy(beans.get(id),beans).getProxy();
}
/**
* 容器中放入对象
*
* @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();
}
}
JDKDynamicProxy:
package com.tgb.config;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Map;
import org.jdom.Element;
/***
* ClassName: JDKDynamicProxy
* @Description: AOP实现对业务容器 的增强,对业务容器中每个对象增强 服务类中的方法,根据 关系容器配置,
* 实现特性方法增强
* @author qmx
*
*/
public class JDKDynamicProxy implements InvocationHandler {
private Object target;//被代理类
//对象集合(包含服务类,关系类和业务类)
private Map<String, Object> aspectObject;
public JDKDynamicProxy(Object target, Map<String, Object> aspectMap) {
this.target = target;
this.aspectObject = aspectMap;
}
//获取代理对象
@SuppressWarnings("unchecked")
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target
.getClass().getInterfaces(), this);
}
//回调对象,根据传入对象调用代理类方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//获取对象关系
List beforeList = (List) aspectObject.get("aspectbefore");
//回调服务对象方法
invokeAspectName(beforeList, method, args);
//回调代理对象方法
Object result = method.invoke(target, args);
return result;
}
/**
* 拦截方法匹配
*
* @param beforeList
* 拦截器的所有对象
* @param method
* @param args
* @throws NoSuchMethodException
* @throws SecurityException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
*/
public void invokeAspectName(List beforeList, Method method, Object[] args)
throws NoSuchMethodException, SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
if (beforeList != null) {
for (int i = 0; i < beforeList.size(); i++) {
Element element = (Element) beforeList.get(i);
String aspectClass = element.getAttributeValue("ref");// 获取容器中切入类名称
String aspectName = element.getAttributeValue("aspectMethod");// 执行的切入方法
Class clazz = aspectObject.get(aspectClass).getClass(); // 获取切入类
String elementMethod = element.getAttributeValue("method");// 获取被切入类方法
if (aspectName == null) {
Method[] methods = clazz.getMethods();
for (int j = 0; j < methods.length; j++) {
System.out.println("获取全部公共方法的方法:" + methods[j].toString());
}
} else {
if (method.getName().equals(elementMethod)) {
Method jinectmethod = clazz.getMethod(aspectName, Object.class); // 反射调用切入类方法
jinectmethod.invoke(aspectObject.get(aspectClass), args);
}
}
}
}
}
}
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( this.getClass()+"-----userDao.save()-----");
}
}
User:
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>
<!-- 服务类 -->
<bean id="aspectBean" class="com.tgb.config.AspectBean"></bean>
<bean id="aspectBean2" class="com.tgb.config.AspectBean2"></bean>
<aop isaop="true"></aop>
<!-- 关系配置(业务与服务配置) -->
<aspectbefore ref="aspectBean" method="save" aspectMethod="save"></aspectbefore>
<aspectbefore ref="aspectBean2" method="before" aspectMethod="after"></aspectbefore>
<aspectafter ref="aspectBean" method="after" aspectMethod="before"></aspectafter>
</beans>
运行之后的效果为:
-----测试一
---Save1-日志--
class com.tgb.daoImpl.UserDaoImpl-----userDao.save()-----
相关文章推荐
- 一个jar包里的网站
- 一个jar包里的网站之文件上传
- 一个jar包里的网站之返回对媒体类型
- Spring和ThreadLocal
- Spring Boot 开发微服务
- Spring整合Quartz(JobDetailBean方式)
- Spring整合Quartz(JobDetailBean方式)
- 模拟Spring的简单实现
- Spring整合WebSocket应用示例(上)
- spring+html5实现安全传输随机数字密码键盘
- Spring中属性注入详解
- springmvc 发送ajax出现中文乱码的解决方法汇总
- SpringMVC框架下JQuery传递并解析Json格式的数据是如何实现的
- struts2 spring整合fieldError问题
- spring的jdbctemplate的crud的基类dao
- 读取spring配置文件的方法(spring读取资源文件)
- Spring Bean基本管理实例详解
- java实现简单美女拼图游戏
- 浅析Java中的set集合类型及其接口的用法