本文没有去探寻源码,只是根据现象去推理一下:
1 定义切面类:
package main.daoImpl;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class LogAnnotationAspect {
@Pointcut("execution(* main.daoImpl.*.*(..))")
public void allMethod() {}
@Before("allMethod()")
public void before(JoinPoint jp) {
System.out.println("Args:" + jp.getArgs());
System.out.println("Kind:" + jp.getKind());
System.out.println("Signature:" + jp.getSignature());
System.out.println("Target:" + jp.getTarget());
System.out.println("this:" + jp.getThis());
System.out.println("正在进行权限校验!before...");
System.out.println(jp.getSignature().getName());
if (jp.getSignature().getName().equals("login")) {
}
}
@After("allMethod()")
public void after() {
System.out.println("结束调用!after...");
}
@Around("allMethod()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕! around...");
pjp.proceed();
}
@AfterReturning(pointcut="allMethod()", returning="rvt")
public void afterReturning(Object rvt) {
System.out.println("rrrrrrrrrrrrrrrrrrrrrrrr " + rvt + " rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr");
}
@AfterThrowing("allMethod()")
public void afterThrow() {
System.out.println("after throwing...");
}
}
2 目标类
(1)目标类不实现接口:
package main.daoImpl;
import main.dao.TestDao;
public class TestDaoImpl {
public String test() throws Exception {
System.out.println("test main...");
return "test data!";
}
测试代码:
@Test
public void test() {
try {
TestDaoImpl testDaoImpl = (TestDaoImpl)context.getBean("testDaoImpl");
System.out.println("current class: " + testDaoImpl.getClass().getName());
System.out.println("parent class or interface : " + testDaoImpl.getClass().getSuperclass().getName());
System.out.println("is aop proxy: " + AopUtils.isAopProxy(testDaoImpl));
System.out.println("is cglib proxy: " + AopUtils.isCglibProxy(testDaoImpl));
System.out.println("is jdk proxy: " + AopUtils.isJdkDynamicProxy(testDaoImpl));
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
测试结果:
current class: main.daoImpl.TestDaoImpl$$EnhancerByCGLIB$$a6cb1969
parent class or interface : main.daoImpl.TestDaoImpl
is aop proxy: true
is cglib proxy: true
is jdk proxy: false
从获取的testDaoImpl的class名称为:main.daoImpl.TestDaoImpl$$EnhancerByCGLIB$$a6cb1969,熟悉cglib动态代理的应该知道,这类名称符合cglib动态代理生成类的命名,而且testDaoImpl父类的名称为:main.daoImpl.TestDaoImpl,也就是testDaoImpl继承了类main.daoImpl.TestDaoImpl,此恰恰符合cglib动态代理的特征;所以当目标类没有实现接口时,spring aop使用cglib动态代理生成一个代理类,把切面类
中配置的通知织入到动态代理类内,代理类调用方法时,就会触发通知。
(2)目标类实现接口:
package main.daoImpl;
import main.dao.TestDao;
public class TestDaoImpl implements TestDao {
public String test() throws Exception {
System.out.println("test main...");
return "test data!";
}
}
切面类和上面一致,测试代码为:
@Test
public void test() {
try {
TestDao testDaoImpl = (TestDao)context.getBean("testDaoImpl");
System.out.println("current class: " + testDaoImpl.getClass().getName());
System.out.println("parent class or interface : " + testDaoImpl.getClass().getSuperclass().getName());
System.out.println("is aop proxy: " + AopUtils.isAopProxy(testDaoImpl));
System.out.println("is cglib proxy: " + AopUtils.isCglibProxy(testDaoImpl));
System.out.println("is jdk proxy: " + AopUtils.isJdkDynamicProxy(testDaoImpl));
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
测试结果:
current class: $Proxy13
parent class or interface : java.lang.reflect.Proxy
is aop proxy: true
is cglib proxy: false
is jdk proxy: true
testDaoImpl类名为$Proxy13, 继承了 java.lang.reflect.Proxy,由此可知当目标类实现接口的时候,spring aop 使用jdk的动态代理生成动态代理类把通知织入到动态代理类内
从上面的代码可知,spring aop的总体逻辑为,根据目标类是否实现接口来选择使用jdk还是使用cglib来生成代理类,把通知中的逻辑织入到代理类中