标签:流程 ext abstract compile ons row *** com 注入
public class TraceTest {
public static void main(String args[]) {
TraceTest test = new TraceTest();
test.rpcCall();
}
// 虽然 intellij 没有给出提示,但是这个 Trace 还是成功的
@Trace
public void rpcCall() {
System.out.println("call rpc");
}
}
@Aspect
public class TraceAspect {
@Pointcut("@annotation(Trace)")
public void tracePointcutDefinition() {}
@Around("@annotation(Trace) && execution(* *(..))")
public Object aroundTrace(ProceedingJoinPoint pjp) throws Throwable {
Object returnObj = null;
try {
System.out.println("before traced method started...");
returnObj = pjp.proceed();
} catch (Throwable throwable) {
throw throwable;
} finally {
System.out.println("after traced method executed...");
}
return returnObj;
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Trace {
}
//before traced method started...
//call rpc
//after traced method executed...
按说使用 Spring AOP 是需要容器来注入的,因为容器会自动的把需要注入的代码放到生成的代理类中,但是从上面的例子我们直接 New 了一个实例,但是这个 new 出来的实例就是有被织入的代码,那么它是如何实现的呢?
AOP 有编译时和运行时注入,上面这个例子在编译时已经注入完毕了,生成的 .class 文件已经是修改以后的了,所以不需要再使用容器,来看一下 pom 配置
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
public void rpcCall();
Code:
0: getstatic #46 // Field ajc$tjp_0:Lorg/aspectj/lang/JoinPoint$StaticPart;
3: aload_0
4: aload_0
5: invokestatic #52 // Method org/aspectj/runtime/reflect/Factory.makeJP:(Lorg/aspectj/lang/JoinPoint$StaticPart;Ljava/lang/Object;Ljava/lang/Object;)Lorg/aspectj/lang/JoinPoint;
8: astore_1
9: aload_0
10: aload_1
11: invokestatic #71 // Method aspectjaop/annotation/TraceAspect.aspectOf:()Laspectjaop/annotation/TraceAspect;
14: aload_1
15: checkcast #59 // class org/aspectj/lang/ProceedingJoinPoint
18: invokestatic #75 // Method rpcCall_aroundBody1$advice:(Laspectjaop/annotation/TraceTest;Lorg/aspectj/lang/JoinPoint;Laspectjaop/annotation/TraceAspect;Lorg/aspectj/lang/ProceedingJoinPoint;)Ljava/lang/Object;
21: pop
22: return
所以,maven aspectj 插件在编译的时候会把代码织入到生成的 .class 文件中,这是 AOP 的一个办法
我们要研究的是 Spring AOP
public class Logging {
public void beforeAdvice() {
System.out.println("Going to setup student profile.");
}
public void afterAdvice() {
System.out.println("Student profile has been setup.");
}
public void afterReturningAdvice(Object retVal) {
System.out.println("Returning returning advice ***** :");
}
public void AfterThrowingAdvice(IllegalArgumentException ex) {
System.out.println("There has been an exception: " + ex.toString());
}
}
public class Student {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void ExceptionRaised() {
System.out.println("this is exception message ");
}
}
public class MainApp {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("bean.xml");
Student student = (Student) context.getBean("student");
student.getName();
student.getAge();
student.ExceptionRaised();
}
}
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.10</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
第一个例子不需要 aspectjweaver 但是第二个例子却少不了。第一个例子需要 aspectj-maven-plugin 但是第二个例子是不需要的,因为 spring context 会托管注入这一流程, 后续的 Spring 章节就是用来分析 Spring AOP 的例子是如何实现的,帮助研究的代码就是例2
下面来分析 AOP 的应用流程。因为例子中被织入代码的类型不是接口,所以动态代理的实现应该是 CGLIB 而不是 JdkDynamicProxy
分析的切入点是函数 getProxy,知道了是 cglib 的 getProxy 函数,就把断点设在这个函数体内,根据函数的返回,能够知道整个调用栈, 也可以根据 intellij idea 的 thread stack 直接找到调用栈。
AbstractAutowireCapableBeanFactory.doCreateBean()
AbstractAutowireCapableBeanFactory.initializeBean()
AbstractAutowireCapableBeanFactory.postProcessBeforeInitialization()
AbstractAutowireCapableBeanFactory.postProcessAfterInitialization()
AbstractAdvisorAutoProxyCreator.createProxy
DefaultAopProxyFactory.createAopProxy // 这里选择 JdkDynamicProxy 或者 CGLibProxy
createProxy// 根据具体选取的 AOP proxy 构造代理实例
从上面的代理里,可以明确下面几点问题:
看代码的时候还是有不理解的地方
其实 Cglib 构造动态代理的方式还是蛮简单,不需要过多分析。它就是找到各种 advisor 然后各种 set enhancer 就行了,但是反观 JdkDynamicProxy 就复杂些,因为 JdkDynamicProxy 的构造方法有些复杂。首先,JdkDynamicProxy 需要用到 advisedSupport, 在里面填好 advisor 和 targetClass 然后 JdkDynamicProxy 继承 InvocationHandler
原文:大专栏 AOP spring source code analysis
AOP spring source code analysis
标签:流程 ext abstract compile ons row *** com 注入
原文地址:https://www.cnblogs.com/petewell/p/11612070.html