AOP的实现者
AOP工具的设计目标是把横切的问题(如性能监视、事务管理)模块化。使用类似于OOP的方式进行切面的编程工作。位于AOP工具核心的是连接点模型,它提供了一种机制,可以识别出在哪里发生了横切。
AspectJ
AspectJ是语言级的AOP实现,2001年由Xerox PARC的AOP小组发布。AspectJ扩展了Java语言,定义了AOP语法,能够在编译器提供横切代码的织入,所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。
AspectWerkz
基于Java的简单、动态、轻量级的AOP框架,2002年发布。支持运行期或类装载期织入横切代码,所以它拥有一个特殊的类装载器。现在已与AspectJ项目合并,合作的第一个版本是AspectJ 5,扩展AspectJ语言,以基于注解的方式支持类似AspectJ的代码风格。
JBoss AOP
2004作为JBoss应用服务器的扩展功能发布。
Spring AOP
Spring AOP 使用纯Java实现,它不需要专门的编译过程,不需要特殊的类装载器,它在运行期通过代理方式想目标类织入增强代码。Spring并不尝试提供最完整的AOP实现,相反,它侧重于提供一种和IoC容器整合的AOP实现,用以解决企业级开发中的常见问题。在Spring中,我们可以无缝地将Spring AOP、IoC和AspectJ整合在一起。
AOP联盟
AOP联盟(aopalliance.sourceforge.net)是众多开源AOP项目的联合组织,该组织的目的是为了制定一套规范描述AOP的标准,定义标准的AOP接口,以便各种遵守标准的具体实现可以相互调用。现以成为事实上的标准。
Spring对AOP的支持
Spring在2.0以后对AOP功能进行了重要的增强,主要表现在以下几个方面:
- 新增了基于Schema的配置支持,为AOP专门提供了aop命名空间。
- 新增了对AspectJ切点表达式语言支持。使用和@AspectJ相同风格的注解,并通过AspectJ提供的注解库和解析库处理切点。当然,由于Spring只支持方法级的切点,所以仅对@AspectJ提供了有限的支持。
- 可以无缝地继承AspectJ,AspectJ提供了语言级切面的实现。
我们所说的Spring AOP,它包括基于XML配置的AOP和基于@AspectJ注解的AOP,这两种方法虽然在配置切面时的表现方式不同,但底层都是采用动态代理技术(JDK代理或CGLib代理)。Spring可以集成AspectJ,但AspectJ本身并不属于Spring AOP的范畴。
在一般情况下,对于开发JAVAEE企业应用的开发者而言,Spring AOP已经可以满足使用的要求,虽然AspectJ提供对AOP更为细致的实现,但像实例化切面、属性访问切面、条件切面等功能在实际应用中并不常用。
如果是基于JDK5.0的项目,推荐使用Spring提供的@AspectJ配置方式,因为这种方式能以更简单的更直接的方式应用切面。
ProxyFactoryBean(aspectj方案则是AspectJProxyFactory)
public Object getObject() throws BeansException { initializeAdvisorChain(); if (isSingleton()) { return getSingletonInstance(); } else { if (this.targetName == null) { logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " + "Enable prototype proxies by setting the 'targetName' property."); } return newPrototypeInstance(); } }
ProxyCreatorSupport
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); }
DefaultAopProxyFactory
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface()) { return new JdkDynamicAopProxy(config); } return CglibProxyFactory.createCglibProxy(config); } else { return new JdkDynamicAopProxy(config); } }
我们回忆一下我们做过的jdk代理的例子:
UserMgr mgr = new UserMgrImpl(); InvocationHandler h = new TransactionHandler(mgr); UserMgr u = (UserMgr) Proxy.newProxyInstance(UserMgr.class, h);
生成的代理是比如$Proxy34,h是$Proxy34的成员变量,
public class Proxy implements java.io.Serializable { /** prefix for all proxy class names */ private final static String proxyClassNamePrefix = "$Proxy"; /** * the invocation handler for this proxy instance. * @serial */ protected InvocationHandler h; }
在spring aop中正是JdkDynamicAopProxy。那么重点来了,我们就从JdkDynamicAopProxy的invoke方法看起:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Class<?> targetClass = null; Object target = null; try { if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // May be null. Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } // Get the interception chain for this method. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. if (chain.isEmpty()) { // We can skip creating a MethodInvocation: just invoke the target directly // Note that the final invoker must be an InvokerInterceptor so we know it does // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); } else { // We need to create a method invocation... invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. retVal = invocation.proceed(); } // Massage return value if necessary. Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
ReflectiveMethodInvocation implements ProxyMethodInvocation extends MethodInvocation extends Invocation extends Joinpoint
public Object proceed() throws Throwable { // We start with an index of -1 and increment early. if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. return proceed(); } } else { // eg. ExposeInvocationInterceptor // It's an interceptor, so we just invoke it: The pointcut will have // been evaluated statically before this object was constructed. return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
package org.aopalliance.intercept; // Aop联盟 import java.lang.reflect.AccessibleObject; public interface Joinpoint { Object proceed() throws Throwable; Object getThis(); AccessibleObject getStaticPart(); }
interceptor.invoker - eg. MethodBeforeAdviceInterceptor
public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); return mi.proceed(); // 又回归到了上面的调用 }
值得注意的是,虽然切面可以只用到一个类的部分方法上,但我们调用其他方法时,仍然会经历上面的逻辑,此时拦截器链里只有一个interceptor - ExposeInvocationInterceptor
public Object invoke(MethodInvocation mi) throws Throwable { MethodInvocation oldInvocation = invocation.get(); invocation.set(mi); try { return mi.proceed(); } finally { invocation.set(oldInvocation); } }
Aop应用参考:
一、分库分表http://wely.iteye.com/blog/2275725
二、方法性能监控
package com.itlong.bjxizhan.support.web.service.monitor; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; /** * Created by shenhongxi on 2016/8/10. */ @Aspect public class MonitorAspect { private String tagPrefix; @Around( value = "execution(* *(..)) && @annotation(monitor)", argNames = "pjp,monitor" ) public Object doUmpLogging(ProceedingJoinPoint pjp, Monitor monitor) throws Throwable { // String tag = monitor.tag(); // boolean heart = monitor.heart(); long start = System.currentTimeMillis(); // record invocation (times) Object obj = null; try { obj = pjp.proceed(); } catch (Exception e) { // record error throw e; } finally { long end = System.currentTimeMillis(); // record time -> end - start } return obj; } public String getTagPrefix() { return tagPrefix; } public void setTagPrefix(String tagPrefix) { this.tagPrefix = tagPrefix; } } @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) public @interface Monitor { String DEFAULT_TAG_NAME = "@@USE_METHOD_NAME"; String tag() default "@@USE_METHOD_NAME"; String message() default ""; boolean heart() default false; }
另外,性能监控拦截器可参考org.springframework.aop.interceptor.PerformanceMonitorInterceptor
相关推荐
NULL 博文链接:https://zhang-yingjie-qq-com.iteye.com/blog/319927
Spring框架系列(9) - Spring AOP实现原理详解之AOP切面的实现.doc
Spring框架系列(11) - Spring AOP实现原理详解之Cglib代理实现.doc
AOP的意思就是面向切面编程。本文主要是通过梳理JDK中自带的反射机制,实现 AOP动态代理模式,这也是Spring AOP 的实现原理
spring ioc容器初始化流程图 spring ioc容器依赖注入流程图 spring aop实现原理流程图
Spring AOP的实现机制中文版,动态代理及原理,自定义类加载器
Spring AOP面向方面编程原理Spring AOP面向方面编程原理Spring AOP面向方面编程原理Spring AOP面向方面编程原理Spring AOP面向方面编程原理Spring AOP面向方面编程原理Spring AOP面向方面编程原理
2、能够清楚的知道如何用spring aop实现自定义注解以及注解的逻辑实现 (需要知道原理的请看spring aop源码,此处不做赘述) 3、可在现有源码上快速进行功能扩展 4、spring boot,mybatis,druid,spring aop的使用
AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。本文给大家介绍Spring 的aop实现原理,感兴趣的朋友一起学习吧
主要为大家详细介绍了Spring AOP的实现原理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
springAOP配置实现动态代理,有利于熟悉动态代理原理,深入了解spring。
NULL 博文链接:https://arne3166.iteye.com/blog/1046340
什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共...
Spring Aop的底层实现技术 --- Jdk动态代理原理 很不错的一篇文章
IoC原理分析 基于XML的IoC实现 ... Spring AOP基于XML和注解的实现 Spring应用之Spring JDBC实现 Spring应用之JdbcDaoSupport Spring应用之事务支持 Spring与Mybatis整合
通过详细解析Spring AOP的源码,本文揭示了其背后的核心原理和实现机制。Spring AOP主要基于动态代理模式,它允许开发者在不改变原有代码结构的情况下,增加额外的行为。这主要通过定义“切面(Aspects)”和“通知...
本代码通过使用spring aop+ehcache的技术,实现了方法级别的查询缓存,主要原理是 方法的完整路径+方法参数值,作为key,放入cache中,下次访问时先判断cache中是否有该key.
spring aop详解,详细地讲述了spring中aop的实现,实现原理,实现过程。
这两种代理方式在Spring AOP中起到关键作用,用于实现横切关注点的切面编程。通过学习它们的原理和实际应用,您将能够更好地理解和利用Spring AOP来提高您的应用程序的可维护性和可扩展性。 内容亮点: JDK动态...
主要介绍了Spring AOP的实现原理详解及实例的相关资料,需要的朋友可以参考下