程序员人生 网站导航

动态代理实现Spring Aop

栏目:框架设计时间:2016-06-25 15:32:16

引言


我们在前两篇文章中,都为这篇做了铺垫,我们现在来做这样1件事情,在业务逻辑中添加Aop的非业务逻辑。



AopClinetTest:

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: AopClientTest * @Description: TODO(这里用1句话描写这个类的作用) * @author [qmx] * @date * */ public class AopClientTest { 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"); userDao.update(user); } }

AspectCacheBean:


package com.tgb.config; import com.tgb.util.MethodCatch; /** * @ClassName: AspectCachBean * @Description: * 缓存服务类,实现了对缓存的,前置,后置, 保存的方法 * @author [qmx] * @date * */ public class AspectCachBean { @MethodCatch(methodName="cacheBefore") public void cacheBefore(Object proxy) { System.out.println("---这是切入 类AspectCachBean cacheBefore()-方法--"); } @MethodCatch(methodName="cacheAfter") public static void cacheAfter(Object proxy) { System.out.println("---这是切入 类AspectCachBean cacheAfter()-方法--"); } @MethodCatch(methodName="cacheSave") public void cacheSave(Object proxy){ System.out.println("---这是切入 类AspectCachBean cacheSave()-方法--"); } }

AspectCertifiyBean:

package com.tgb.config; import com.tgb.util.MethodCatch; /** * * @ClassName: AspectCertifiyBean * @Description: 认证服务类,提供了认证前, 认证后,认证保存的方法 * @author [qmx] * @date * */ public class AspectCertifiyBean { @MethodCatch(methodName = "certifiyBefore") public void certifiyBefore(Object proxy) { System.out.println("---这是切入 类AspectCertifiyBean certifiyBefore()-方法--"); } @MethodCatch(methodName = "certifyAfter") public void certifyAfter(Object proxy) { System.out.println("---这是切入 类AspectCertifiyBean certifyAfter()-方法--"); } @MethodCatch(methodName = "certifySave") public void certifySave(Object proxy) { System.out.println("---这是切入 类AspectCertifiyBean certifySave()-方法--"); } }

BeanFactory:


package com.tgb.config; import java.util.List; import java.util.Map; /** * * @ClassName: ContainerBeans * @Description: 容器接口,提供容器公共服务方法, 增加,删除,遍历,获得对象,遍历类型,容器大小等方法 * @author [qmx] * @date * */ 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.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; import net.sf.cglib.asm.ClassVisitor; import org.jdom.Document; import org.jdom.Element; import org.jdom.input.SAXBuilder; /*** * * * @author 容器组装类, 装载 业务容器 和 切入容器。 分别将其中的 颗粒装载到各自的 beans 中 */ public class ClassPathXmlApplicationContext implements BeanFactory { // 业务容器beans private Map<String, Object> containerBeans = new HashMap<String, Object>(); // 切面容器beans private Map<String, Object> aspectBeans = new HashMap<String, Object>(); // 设置是不是需要aop private boolean isAop = true; /* * 构造函数加载个容器内对象 */ public ClassPathXmlApplicationContext() throws Exception { SAXBuilder sb = new SAXBuilder(); // 扫描业务容器对象 Document containerDoc = sb.build(Thread.currentThread().getContextClassLoader() .getResourceAsStream("beans.xml")); // 扫描切入容器对象 Document aspectDoc = sb.build(Thread.currentThread().getContextClassLoader() .getResourceAsStream("aspecbeans.xml")); // 设置切面容器 getAspectBeans(aspectDoc); // 设置业务容器bean getContainerBeans(containerDoc); } /*** * 设置业务容器装配 * @param doc * @throws ClassNotFoundException * @throws IllegalAccessException * @throws InstantiationException * @throws SecurityException * @throws NoSuchMethodException * @throws InvocationTargetException * @throws IllegalArgumentException */ private void getContainerBeans(Document doc) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException { //读取文档根目录 Element root = doc.getRootElement(); //获得aop节点信息 Element aopElement = (Element) root.getChildren("aop").get(0); //aop节点属性 isAop = Boolean.parseBoolean(aopElement.getAttributeValue("isaop")); //获得bean节点 List list = root.getChildren("bean"); // 前置增强节点 List aopBeforeList = root.getChildren("aspectbefore"); //后置节点 List aopAfterList = root.getChildren("aspectafter"); //辨别增强节点是不是有配置,放入bean关系容器中 if (aopBeforeList != null) { containerBeans.put("aspectbefore", aopBeforeList); } if (aopAfterList != null) { containerBeans.put("aspectafter", aopAfterList); } //调用设备对象方法,装配业务对象 putAllBeans(list, containerBeans); } /** * 设置切入容器装配对象 * * @param doc * @throws InstantiationException * @throws IllegalAccessException * @throws ClassNotFoundException * @throws InvocationTargetException * @throws IllegalArgumentException * @throws SecurityException * @throws NoSuchMethodException */ private void getAspectBeans(Document doc) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException { //读取文档根目录 Element root = doc.getRootElement(); List aspectElements = root.getChildren("aspectbean");//读取切入配置文件 putAllBeans(aspectElements,aspectBeans); } /** * 对象装配方法 * @param list 读取的配置文件 * @param allBeans 设置装配的容器对象 * @throws InstantiationException * @throws IllegalAccessException * @throws ClassNotFoundException * @throws NoSuchMethodException * @throws SecurityException * @throws IllegalArgumentException * @throws InvocationTargetException */ public void putAllBeans(List list, Map<String, Object> allBeans) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException { for (int i = 0; i < list.size(); i++) { //获得传入父亲节点中的每一个子节点,为行element Element element = (Element) list.get(i); //获得子节点中的id属性 String id = element.getAttributeValue("id"); //获得子节点中的class属性 String clazz = element.getAttributeValue("class"); //实例化class Object o = Class.forName(clazz).newInstance(); //将实例化的class放入容器 allBeans.put(id, o); //for循环获得 bean中的 属性property for (Element propertyElement : (List<Element>) element .getChildren("property")) { //获得property属性中的name属性 String name = propertyElement.getAttributeValue("name"); // userDAO //获得property属性中的ref属性 String bean = propertyElement.getAttributeValue("ref"); // //获得子属性的试题 Object beanObject = allBeans.get(bean);// UserDAOImpl //调用 依赖实体中的set方法(为籽实体的方法) String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1); 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 containerBeans.get(id); } return new JDKDynamicProxy(containerBeans.get(id), aspectBeans, containerBeans) .getProxy(); } /** * 容器中放入对象 * * @param k * @param v * @return */ public Object put(String k, Object v) { return containerBeans.put(k, v); } /** * 打印容器中所有对象类型 */ public void printTypeName() { Set<String> hashSet = new HashSet<String>(); Set<Entry<String, Object>> entryset = containerBeans.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 = containerBeans.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) { containerBeans.remove(id); } /*** * 打印所有注入对象 */ public void printAllbeanId() { Set<Entry<String, Object>> entryset = containerBeans.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 containerBeans.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.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.jdom.Element; import com.tgb.util.MethodCatch; /* @ClassName: JDKDynamicProxy * @Description: AOP实现对业务容器 的增强,对业务容器中每一个对象增强 服务类中的方法,根据 关系容器配置, * 实现特性方法增强 * @author [qmx] */ public class JDKDynamicProxy implements InvocationHandler { private Object target; private Map<String, Object> aspectBeans; // 切入容器 private Map<String, Object> containerBeans;// 业务容器 /** * 代理类获得代理对象,业务容器,切面容器 * * @param target * 被代理对象 * @param aspectBeans * 切面容器 * @param containerBeans * 业务容器 */ public JDKDynamicProxy(Object target, Map<String, Object> aspectBeans, Map<String, Object> containerBeans) { this.target = target; this.aspectBeans = aspectBeans; this.containerBeans = containerBeans; } @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) containerBeans.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判断获得的集合是不是为空,若为空则履行所有服务对象的所有方法 if (beforeList != null && beforeList.size() != 0) { //for循环遍历 集合对象中的对象,获得每一个对象,履行该对象中的方法 for (int i = 0; i < beforeList.size(); i++) { Element element = (Element) beforeList.get(i); //获得每一个对象 String aspectClass = element.getAttributeValue("aspectId");// 获得容器中切入类名称 String aspectName = element.getAttributeValue("aspectMethod");// 履行的切入方法 //若对象为空,则说明 if (aspectBeans.get(aspectClass) == null) { System.out.println("未找到该切入类,请查看配置的切入类名称是不是正确"); return; } Class clazz = aspectBeans.get(aspectClass).getClass(); // 获得切入类 String elementMethod = element.getAttributeValue("method");// 获得被切入类方法 // 未声明切入方法,则履行所有切入方法 if (aspectName == null) { if (method.getName() != null) { if (method.getName().equals(elementMethod)) { getAllMethod(clazz, aspectClass, args); } } aspactAllClass(aspectClass, args==null? new Object[1]: args); } else { //if判断是不是 声明l切入方法,若是则履行指定切入方法,否则履行所有方法 if (method.getName().equals(elementMethod)) { Method jinectmethod = clazz.getMethod(aspectName, Object.class); // 反射调用切入类方法 jinectmethod.invoke(aspectBeans.get(aspectClass), args==null? new Object[1]: args); } aspactAllClass(aspectClass, args==null? new Object[1]: args); } } } //传入集合对象为空,则履行多有对象的所有方法 else { Iterator aspectClass = aspectBeans.entrySet().iterator(); while (aspectClass.hasNext()) { Entry<String, Object> entry = (Entry<String, Object>) aspectClass.next(); Class clazz = entry.getValue().getClass();// 获得切入类 Method[] methods = clazz.getMethods(); for (int j = 0; j < methods.length; j++) { // 读取切入类注解中的所有方法 if (methods[j].isAnnotationPresent(MethodCatch.class) == true) { MethodCatch methodCatch = methods[j] .getAnnotation(MethodCatch.class);// 获得注解类 Method jinectmethod = clazz.getMethod(methodCatch.methodName(), Object.class); // 反射调用切入类方法 jinectmethod.invoke(entry.getValue(), args==null? new Object[1]: args); } } } } } /** * * @Title: aspactAllClass * @Description: 履行容器中所有服务类中的方法(除指定的对象不履行,其他的都履行) * @param @param aspectId * @param @param args * @param @throws NoSuchMethodException * @param @throws SecurityException * @param @throws IllegalAccessException * @param @throws IllegalArgumentException * @param @throws InvocationTargetException 设定文件 * @return void 返回类型 * @throws */ public void aspactAllClass(String aspectId, Object[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Iterator aspectClass = aspectBeans.entrySet().iterator(); //while循环获得服务集合中的所有对象,调用该对象中的方法 while (aspectClass.hasNext()) { Entry<String, Object> entry = (Entry<String, Object>) aspectClass.next(); if (!aspectId.equals(entry.getKey())) { Class clazz = entry.getValue().getClass();// 获得切入类 Method[] methods = clazz.getMethods(); for (int j = 0; j < methods.length; j++) { // 读取切入类注解中的所有方法 if (methods[j].isAnnotationPresent(MethodCatch.class) == true) { MethodCatch methodCatch = methods[j] .getAnnotation(MethodCatch.class);// 获得注解类 Method jinectmethod = clazz.getMethod(methodCatch.methodName(), Object.class); // 反射调用切入类方法 jinectmethod.invoke(entry.getValue(), args==null? new Object[1]: args); } } } } } /** * 履行某个服务类中的所有方法 * @Title: getAllMethod * @Description: TODO(这里用1句话描写这个方法的作用) * @param @param clazz * @param @param aspectClass * @param @param args * @param @throws IllegalAccessException * @param @throws IllegalArgumentException * @param @throws InvocationTargetException * @param @throws NoSuchMethodException * @param @throws SecurityException 设定文件 * @return void 返回类型 * @throws */ public void getAllMethod(Class clazz, String aspectClass, Object[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { Method[] methods = clazz.getMethods(); for (int j = 0; j < methods.length; j++) { if (methods[j].isAnnotationPresent(MethodCatch.class) == true) { MethodCatch methodCatch = methods[j].getAnnotation(MethodCatch.class);// 获得注解类 Method jinectmethod = clazz.getMethod(methodCatch.methodName(), Object.class); // 反射调用切入类方法 jinectmethod.invoke(aspectBeans.get(aspectClass), args==null? new Object[1]: args); } } } }

UserDao:


package com.tgb.dao; import com.tgb.domain.User; /** * 用于操作用户信息类。 * @ClassName: UserDao * @Description: TODO(这里用1句话描写这个类的作用) * @author [qmx] * @date * */ public interface UserDao { void save(User user); void update(User user); public void delete( User user); }

UserDaoImpl:


package com.tgb.daoImpl; import com.tgb.dao.UserDao; import com.tgb.domain.User; /** * 用户操作类,用于添加用户信息 * * @ClassName: UserDaoImpl * @Description: TODO(这里用1句话描写这个类的作用) * @author [qmx] * @date * */ public class UserDaoImpl implements UserDao { @Override public void save(User user) { System.out.println("这是业务类 " + this.getClass() + "-----的 userDao.save()方法-----"); } @Override public void update(User user) { System.out.println("这是业务类 " + this.getClass() + "-----的 userDao.update()方法-----"); } @Override public void delete(User user) { System.out.println("这是业务类 " + this.getClass() + "-----的 userDao.delete()方法-----"); } }

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; } }

MethodCatch:


package com.tgb.util; /** * 自定义注解类,用于类方法上读取方法名称 */ import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MethodCatch { /** * 用于 获得方法名称 * @Title: methodName * @Description: * @param @return 设定文件 * @return String 返回类型 * @throws */ public String methodName(); }

aspectbeans.xml:


<beans> <!-- 服务类配置 --> <aspectbean id="aspectCachBean" class="com.tgb.config.AspectCachBean"></aspectbean> <aspectbean id="aspectCertifiyBean" class="com.tgb.config.AspectCertifiyBean"></aspectbean> </beans>

beans.xml:

<beans> <!-- 业务类 --> <bean id="UserDao" class="com.tgb.daoImpl.UserDaoImpl" /> <!-- 是不是启用aop --> <aop isaop="true"></aop> <!-- 关系配置 --> <!-- aspectMethod="save" --> <aspectbefore aspectId="aspectCachBean" method="update" aspectMethod="cacheAfter" ></aspectbefore> <aspectbefore aspectId="aspectCertifiyBean" method="update" aspectMethod="certifyAfter" ></aspectbefore> </beans>






------分隔线----------------------------
------分隔线----------------------------

最新技术推荐