AOP(Aspect Orient Programming),一般称为面向方面(切面)编程,作为面向对象的一种补充,
我们将业务处理的主要流程是作为核心关注点,而用于处理系统中分布于各个模块中与核心业务无关的, 比如事务管理、日志、缓存等等,称为横切关注点,AOP的作用就是将核心关注点和横切关注点分离开来。
AOP核心概念
1、切入点(pointcut)
需要要增强的目标方法,比如:你的一个类有很多方法,但是只需要在login方法执行记录一下日志,其他的方法不需要,那么这login方法就是一个切点
2、连接点(joinpoint)
这里指的是方法连接点,连接点可以说是切点的全集。方法有关的前前后后都是连接点。
3、通知(advice)
某个方法在执行前或执行后需要完成的工作,比如在某个方法执行完成后记录一下日志。在什么时候和要完成什么通过方法名中的before,after,around等来实现
4、切面(aspect)
切面是通知和切点的结合,切点和通知共同定义了切面的全部功能——它是什么,在何时何处完成其功能 , 切面就是对横切关注点的抽象
AOP实现的关键在于AOP框架自动创建的AOP代理,
AOP代理主要分为静态代理和动态代理,静态代理的代表为AspectJ;而动态代理则以Spring AOP为代表
Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改原来原来的对象,而是在需要的时候重新生成一个代理对象,这个代理对象包含了目标对象的全部方法,并且在指定的切点做了了处理,而且最终还是回调原对象的方法。
动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。
如果目标类没有实现接口,那就要选择使用CGLIB来动态代理目标类。
CGLIB会让生成的代理类继承当前对象,并在代理类中对代理方法进行强化处理(前置处理、后置处理等)。
在CGLIB底层底层实现是通过ASM字节码处理框架来转换字节码并生成新的代理类
注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
在Spring Aop框架中,MethodInterceptor接口被用来拦截指定的方法,对方法进行增强。
在Aop中每个advistor 里面会有一个advice具体做切面动作,Spring提供了AspectJAfterReturningAdvice,AspectJMethodBeforeAdvice,AspectJAroundAdvice,AspectJAfterAdvice这几个advice,在XML 配置aop时候会指定<aop:after-returning/>,<aop:before/>,<aop:around/>,<aop:after/>
,其实内部就是创建上面对应的这些advice。
从图知道AspectJAfterReturningAdvice和AspectJMethodBeforeAdvice没有实现MethodInterceptor接口,其他两者则实现了该接口。
而Spring Aop的方法拦截器却必须是实现了MethodInterceptor的,所以Spring提供了对应的适配器来适配这个问题,分别是MethodBeforeAdviceAdapter和AfterReturningAdviceAdapter和ThrowsAdviceAdapter。
适配器模式属于结构性模式,它为两个不同接口之间互通提供了一种手段。
下面是 DefaultAdvisorAdapterRegistry类的全部代码, 会默认注册 上面三个适配器,
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable { private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3); /** * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters. */
public DefaultAdvisorAdapterRegistry() { registerAdvisorAdapter(new MethodBeforeAdviceAdapter()); registerAdvisorAdapter(new AfterReturningAdviceAdapter()); registerAdvisorAdapter(new ThrowsAdviceAdapter()); } @Override public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException { if (adviceObject instanceof Advisor) { return (Advisor) adviceObject; } if (!(adviceObject instanceof Advice)) { throw new UnknownAdviceTypeException(adviceObject); } Advice advice = (Advice) adviceObject; if (advice instanceof MethodInterceptor) { // So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice); } for (AdvisorAdapter adapter : this.adapters) { // Check that it is supported.
if (adapter.supportsAdvice(advice)) { return new DefaultPointcutAdvisor(advice); } } throw new UnknownAdviceTypeException(advice); } @Override public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3); Advice advice = advisor.getAdvice(); if (advice instanceof MethodInterceptor) { interceptors.add((MethodInterceptor) advice); } for (AdvisorAdapter adapter : this.adapters) { if (adapter.supportsAdvice(advice)) { interceptors.add(adapter.getInterceptor(advisor)); } } if (interceptors.isEmpty()) { throw new UnknownAdviceTypeException(advisor.getAdvice()); } return interceptors.toArray(new MethodInterceptor[interceptors.size()]); } @Override public void registerAdvisorAdapter(AdvisorAdapter adapter) { this.adapters.add(adapter); } }
以MethodBeforeAdviceAdapter为例子看下:
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable { @Override public boolean supportsAdvice(Advice advice) { return (advice instanceof MethodBeforeAdvice); } @Override public MethodInterceptor getInterceptor(Advisor advisor) { MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice(); return new MethodBeforeAdviceInterceptor(advice); } }
MethodBeforeAdviceInterceptor的代码如下:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable { private MethodBeforeAdvice advice; /** * Create a new MethodBeforeAdviceInterceptor for the given advice. * @param advice the MethodBeforeAdvice to wrap */
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; } @Override public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); return mi.proceed(); } }
可知MethodBeforeAdviceInterceptor继承了MethodInterceptor作为了一个适配器内部委托请求给MethodBeforeAdvice。