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 AOP 实现原理详解之 AOP 切面的实现 Spring AOP 是基于 IOC 的 Bean 加载来实现的,本文主要介绍 Spring AOP 原理解析的切面实现过程。AOP 切面的实现是将切面类的所有切面方法根据使用的注解生成对应 ...
Spring框架中的AOP模块使用了动态代理来实现AOP概念。Spring AOP允许开发者定义切面,并在这些切面中指定拦截的方法。Spring AOP支持不同的代理策略,包括JDK动态代理和CGLIB代理。如果被代理的类没有实现接口,...
**Spring AOP 实现机制详解** Spring AOP(面向切面编程)是Spring框架的核心特性之一,它允许程序员在不修改源代码的情况下,通过“切面”来插入额外的业务逻辑,如日志、事务管理等。AOP的引入极大地提高了代码的...
Spring AOP,全称Aspect Oriented Programming,即面向切面编程,是Spring框架的一个重要特性,用于实现横切关注点的模块化。AOP通过在运行时动态地将代码编织到一起,使得我们可以在不修改原有业务代码的情况下,对...
### Spring AOP面向方面编程原理:AOP概念详解 #### 一、引言 随着软件系统的日益复杂,传统的面向对象编程(OOP)逐渐暴露出难以应对某些横切关注点(cross-cutting concerns)的问题。为了解决这一挑战,面向方面编程...
本文将深入探讨Spring AOP的实现原理,以及如何使用反射来实现动态代理模式。 首先,我们需要了解AOP的基本概念。AOP的核心思想是切面,它包含两个主要部分:切点(Pointcut)和通知(Advice)。切点定义了在程序...
Spring AOP实现原理解析 Spring AOP(Aspect-Oriented Programming)是一种面向方面编程的技术,它可以将公共行为封装到一个可重用模块中,以减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可...
总的来说,JDK动态代理是Spring AOP实现的基础,它允许我们在运行时动态创建代理对象,实现对方法调用的拦截和增强。Spring AOP则在此基础上提供了更高级的抽象,让我们可以方便地定义和管理切面,从而实现更灵活的...
2、能够清楚的知道如何用spring aop实现自定义注解以及注解的逻辑实现 (需要知道原理的请看spring aop源码,此处不做赘述) 3、可在现有源码上快速进行功能扩展 4、spring boot,mybatis,druid,spring aop的使用
AOP(Aspect-Oriented Programming,面向方面编程)是一种编程范式,旨在提供更好的模块化和组织代码的方式,...通过理解Spring AOP的实现原理,开发者可以更好地设计和优化应用程序,提升系统架构的灵活性和可扩展性。
本示例将简要介绍如何在Spring应用中实现AOP,通过实际的代码示例帮助理解其工作原理。 首先,我们要理解AOP的核心概念。AOP是一种编程范式,它允许开发者定义“切面”(Aspects),这些切面封装了特定的关注点,如...
Spring AOP 的底层实现技术 --- Jdk 动态代理原理 JDK 动态代理是 Spring AOP 的底层实现技术,允许开发者在运行期创建接口的代理实例。在 JDK 1.3 以后,JDK 动态代理技术提供了实现 AOP 的绝好底层技术。JDK 动态...
6. **代理(Proxy)**:Spring AOP通过动态代理实现切面的织入。对于接口,使用JDK动态代理;对于非接口类,使用CGLIB动态代理。 Spring的IOC和AOP机制使得开发者能够更专注于业务逻辑,而不是繁琐的依赖管理和横切...
在深入理解 Spring AOP 的源码时,需要熟悉 Spring IoC 的工作原理,以及 AOP 相关的概念,如切点表达式、通知类型等。了解这些基础知识可以帮助我们更好地掌握 Spring AOP 的实现细节。在分析源码时,可以参考作者...
在Spring框架中,AOP(面向切面编程)就是基于Java动态代理来完成的,用于实现横切关注点,如日志、事务管理等。这篇博客的文章链接虽然没有给出具体内容,但我们可以根据Java动态代理和Spring AOP的基本概念来深入...
4. **事务管理Demo**:结合Spring的事务管理特性,展示了如何使用AOP实现数据库操作的事务控制。 通过这些示例,你可以深入理解Spring AOP的工作原理,掌握其配置和使用方式,从而在实际项目中灵活地应用切面编程,...
二、Spring AOP实现原理 1. **代理模式**:Spring AOP采用动态代理技术实现,主要有两种代理方式:JDK动态代理和CGLIB代理。JDK代理用于接口类,CGLIB代理则针对无接口或非代理接口的类。 2. **切面(Aspect)**:...
本篇文章将深入探讨如何使用Spring AOP实现性能监控器,并通过源码分析来理解其工作原理。 首先,我们要了解AOP的核心概念——切面(Aspect)、通知(Advice)、连接点(Join Point)、切入点(Pointcut)和织入...
可以帮助我们更好地理解其工作原理,例如,可以查看`org.springframework.aop.framework.ProxyFactoryBean`、`org.springframework.aop.aspectj.autoproxy.AspectJProxyFactoryBean`、`org.springframework.aop....