adviso结构类图
Spring 中对切点、通知、切面的抽象如下
-
切点:接口 Pointcut,典型实现 AspectJExpressionPointcut
-
通知:典型接口为 MethodInterceptor 代表环绕通知
-
切面:Advisor,包含一个 Advice 通知,PointcutAdvisor 包含一个 Advice 通知和一个 Pointcut
-
代理相关类图
-
AopProxyFactory 根据 proxyTargetClass 等设置选择 AopProxy 实现
-
AopProxy 通过 getProxy 创建代理对象
-
图中 Proxy 都实现了 Advised 接口,能够获得关联的切面集合与目标(其实是从 ProxyFactory 取得)
-
调用代理方法时,会借助 ProxyFactory 将通知统一转为环绕通知:MethodInterceptor
-
adviso增强实现
-
底层的切点实现
-
底层的通知实现
-
底层的切面实现
-
ProxyFactory 用来创建代理
-
如果指定了接口,且 proxyTargetClass = false,使用 JdkDynamicAopProxy
-
如果没有指定接口,或者 proxyTargetClass = true,使用 ObjenesisCglibAopProxy
-
例外:如果目标是接口类型或已经是 Jdk 代理,使用 JdkDynamicAopProxy
-
-
package com.butch.a15;
import com.butch.a13.Target;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
public class A15 {
//切面类
@Aspect
static class MyAspect{
//通知
@Before("execution(* foo())")//切点
public void before(){
System.out.println("==========前置增强=======");
}
@Before("execution(* foo())")
public void after(){
System.out.println("==========后置增强=======");
}
}
public static void main(String[] args) {
/*
两个切面概念
aspect =
通知1(advice) + 切点1(pointcut)
通知2(advice) + 切点2(pointcut)
通知3(advice) + 切点3(pointcut)
...
advisor = 更细粒度的切面,包含一个通知和切点 最终生效 aspect拆解为多个advisor
*/
//advisor切点
AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
aspectJExpressionPointcut.setExpression("execution(* foo())");
//advisor通知
MethodInterceptor advice = new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("==========before");
Object res = methodInvocation.proceed();
System.out.println("=============after");
return res;
}
};
//advisor漆面
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(aspectJExpressionPointcut, advice);
//创建代理
ProxyFactory proxyFactory = new ProxyFactory();
Target1 target1 = new Target1();
proxyFactory.setTarget(target1);
proxyFactory.addAdvisor(advisor);
//设置实现的接口
proxyFactory.setInterfaces(I1.class);
proxyFactory.setProxyTargetClass(true);
I1 proxy = (I1) proxyFactory.getProxy();
System.out.println("proxy.getClass() = " + proxy.getClass());
proxy.bar();
proxy.foo();
}
interface I1 {
void foo();
void bar();
}
static class Target1 implements I1 {
public void foo() {
System.out.println("target1 foo");
}
public void bar() {
System.out.println("target1 bar");
}
}
static class Target2 {
public void foo() {
System.out.println("target2 foo");
}
public void bar() {
System.out.println("target2 bar");
}
}
}
spring代理选择规则
a. proxyTargetClass = false, 目标实现了接口, 用 jdk 实现
b. proxyTargetClass = false, 目标没有实现接口, 用 cglib 实现
c. proxyTargetClass = true, 总是使用 cglib 实现
切点匹配
模拟AOP在进行切点匹配的逻辑
package com.butch.a16;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.transaction.annotation.Transactional;
import java.lang.reflect.Method;
public class A16 {
public static void main(String[] args) throws NoSuchMethodException {
// AspectJExpressionPointcut pt1 = new AspectJExpressionPointcut();
// pt1.setExpression("execution(* bar())");
// System.out.println("pt1.matches(T1.class.getMethod(\"bar\"),T1.class) = " + pt1.matches(T1.class.getMethod("bar"), T1.class)); //true
// System.out.println("pt1.matches(T1.class.getMethod(\"bar\"),T1.class) = " + pt1.matches(T1.class.getMethod("foo"), T1.class)); //false
//
// AspectJExpressionPointcut pt2 = new AspectJExpressionPointcut();
// pt2.setExpression("@annotation(org.springframework.transaction.annotation.Transactional)");
// System.out.println("pt2.matches(T1.class.getMethod(\"bar\"),T1.class) = " + pt2.matches(T1.class.getMethod("bar"), T1.class)); //true
// System.out.println("pt2.matches(T1.class.getMethod(\"bar\"),T1.class) = " + pt2.matches(T1.class.getMethod("foo"), T1.class)); //false
//处理类似上或者接口上注解的匹配
StaticMethodMatcherPointcut pt3 = new StaticMethodMatcherPointcut() {
@Override
public boolean matches(Method method, Class<?> aClass) {
//优先匹配方法上的
MergedAnnotations from = MergedAnnotations.from(method);
if (from.isPresent(Transactional.class)){
return true;
}
//匹配类上的注解,默认在本类寻找,加入TYPE_HIERARCHY在父类和父接口寻找
MergedAnnotations from1 = MergedAnnotations.from(aClass, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY);
if (from1.isPresent(Transactional.class)){
return true;
}
return false;
}
};
System.out.println("pt3.matches(T1.class.getMethod(\"foo\"),T1.class) = " + pt3.matches(T1.class.getMethod("foo"), T1.class));
System.out.println("pt3.matches(T1.class.getMethod(\"foo\"),T1.class) = " + pt3.matches(T1.class.getMethod("bar"), T1.class));
System.out.println("pt3.matches(T1.class.getMethod(\"foo\"),T1.class) = " + pt3.matches(T2.class.getMethod("foo"), T2.class));
System.out.println("pt3.matches(T1.class.getMethod(\"foo\"),T1.class) = " + pt3.matches(T3.class.getMethod("foo"), T3.class));
}
static class T1 {
@Transactional
public void foo() {
}
public void bar() {
}
}
@Transactional
static class T2 {
public void foo() {
}
}
@Transactional
interface I3 {
void foo();
}
static class T3 implements I3 {
public void foo() {
}
}
}