spring主要的特点之一就是面向切面编程,为了实现切面编程需要借助动态代理技术。
首先,定义一个代理管理类,用来创建创建的代理,在代理中调用切面的实现逻辑:
public class ProxyManager { public static <T> T createProxy(final Class<?> targetClass, final List<Proxy> proxyList){ return (T) Enhancer.create(targetClass, new MethodInterceptor() { @Override public Object intercept(Object targetObject, Method targetMethod, Object[] methodParams, MethodProxy methodProxy) throws Throwable { return new ProxyChain(targetClass, targetObject, targetMethod, methodProxy, methodParams, proxyList).doProxyChain(); } }); } }
多个切面使用链表来管理,组成一个切面链,:
public Object doProxyChain() throws Throwable { Object methodResult; if(proxyIndex < proxyList.size()){ Proxy proxy = proxyList.get(proxyIndex); proxyIndex++; methodResult = proxy.doProxy(this); }else { methodResult = methodProxy.invokeSuper(targetObject, methodParams); } return methodResult; }
以事务切面的实现为例:
public class TransactionAspect extends AspectProxy { private static final Logger LOGGER = LoggerFactory.getLogger(AspectProxy.class); private static final ThreadLocal<Boolean> FLAG_HOLDER = new ThreadLocal<Boolean>(); @Override public final Object doProxy(ProxyChain proxyChain)throws Throwable{ Object result = null; Method method = proxyChain.getTargetMethod(); Boolean flag = FLAG_HOLDER.get(); if(flag == null && method.isAnnotationPresent(Transaction.class)){ try { FLAG_HOLDER.set(true); DatabaseHelper.beginTransaction(); result = proxyChain.doProxyChain(); DatabaseHelper.endTransaction(); } catch (Exception e) { LOGGER.error("proxy failure", e); DatabaseHelper.rollbackTransaction(); throw e; } finally { FLAG_HOLDER.remove(); } }else { result = proxyChain.doProxyChain(); } return result; } }
接下来,就需要在框架的对象管理池中在切点出使用动态代理替代原有的对象,这样当调用对象方法时会去调用代理的处理逻辑,实现面向切面的编程。
//根据代理类找到目标类,然后反过来对目标类生成代理类(链) static { try { Map<Class<?>, Set<Class<?>>> proxyMap = createProxyMap(); Map<Class<?>, List<Proxy>> targetMap = createTargetMap(proxyMap); for(Map.Entry<Class<?>, List<Proxy>> targetEntry : targetMap.entrySet()){ Class<?> targetClass = targetEntry.getKey(); List<Proxy> proxyList = targetEntry.getValue(); Object proxy = ProxyManager.createProxy(targetClass, proxyList); BeanHelper.setBean(targetClass, proxy); } } catch (Exception e) { e.printStackTrace(); } } private static Set<Class<?>> createTargetClassSet(Aspect aspect){ Set<Class<?>> targetClassSet = new HashSet<Class<?>>(); Class<? extends Annotation> annotation = aspect.value(); if(annotation != null && !annotation.equals(Aspect.class)){ targetClassSet.addAll(ClassHelper.getClassSetByAnnotation(annotation)); } return targetClassSet; } private static Map<Class<?>, Set<Class<?>>> createProxyMap(){ Map<Class<?>, Set<Class<?>>> proxyMap = new HashMap<Class<?>, Set<Class<?>>>(); Set<Class<?>> proxyClassSet = ClassHelper.getClassSetBySuper(AspectProxy.class); for(Class<?> proxyClass : proxyClassSet){ if(proxyClass.isAnnotationPresent(Aspect.class)){ Aspect aspect = proxyClass.getAnnotation(Aspect.class); Set<Class<?>> targetClassSet = createTargetClassSet(aspect); proxyMap.put(proxyClass, targetClassSet); } } Set<Class<?>> transactionServiceSet = ClassHelper.getClassSetByAnnotation(Service.class); proxyMap.put(TransactionAspect.class, transactionServiceSet); return proxyMap; } private static Map<Class<?>, List<Proxy>> createTargetMap(Map<Class<?>, Set<Class<?>>> proxyMap) throws IllegalAccessException, InstantiationException { Map<Class<?>, List<Proxy>> targetMap = new HashMap<Class<?>, List<Proxy>>(); for(Map.Entry<Class<?>, Set<Class<?>>> proxyEntry : proxyMap.entrySet()){ Class<?> proxyClass = proxyEntry.getKey(); Set<Class<?>> targetClassSet = proxyEntry.getValue(); for(Class<?> targetClass : targetClassSet){ Proxy proxy = (Proxy) proxyClass.newInstance(); if(targetMap.containsKey(targetClass)){ targetMap.get(targetClass).add(proxy); }else { List<Proxy> proxyList = new ArrayList<Proxy>(); proxyList.add(proxy); targetMap.put(targetClass, proxyList); } } } return targetMap; }
相关推荐
Spring,面向切面编程AOP例子!AOP(Aspect Oriented Programming)!
Spring-aop面向切面编程实例 日志系统,权限控制等.
关于Spring框架的aop简介
AOP面向切面编程.ppt
aop,面向切面编程
一直对AOP面向切面编程的理解很模糊的同学可以看看。
aop 面向切面编程 demo,通过一个小案例来讲解,aop在andriod开发中运用
AOP面向切面编程实例,可当作业提交。.net代码亲测,完全正确运行。
2.1 面向切面编程AOP入门 软件系统中的一些功能需要用到应用程序的多个地方,但是我们又不想在每个点都明确调用它们。日志、安全和事务管理的确都很重要,但它们是否为应该被应用对象主动调用呢?如果让应用对象只...
spect Oriented Programming(AOP),面向切面编程,是一个比较热门的话题。AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的...
面向切面编程(AOP)提供另外一种角度来思考程序结构,通过这种方式弥补了面向对象编程(OOP)的不足。 除了类(classes)以外,AOP提供了 切面。切面对关注点进行模块化,例如横切多个类型和对象的事务管理。
AOP面向切面编程的JavaScript实现
aop面向切面编程教学ppt
面向切面编程,是一个比较热门的话题。AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。
C# 面向切面编程实例,有兴趣的朋友可以下载研究!
NULL 博文链接:https://countme.iteye.com/blog/1132555
Spring框架系列(4) - 深入浅出Spring核心之面向切面编程(AOP).doc
SpringBoot之AOP面向切面编程实例
java_AOP面向切面编程
Spring4AOP 面向切面编程实例之方法拦截实例 一下利用Spring4的最后一个版本Spring4.3.9,实现简单的方法拦截实例。 Eclipse 建立java工程,导入必要的jar包,工程目录如下: