Spring-13 AOP 动态通知 & 静态通知
Spring 源码系列文章会遵循由浅入深,由易到难,由宏观到微观的原则,目标是尽量降低学习难度,而不是一上来就迷失在源码当中. 文章会从一个场景作为出发点,针对性的目的性极强的针对该场景对 Spring 的实现原理,源码进行探究学习。该系列文章会让你收获什么? 从对 Spring 的使用者成为 Spring 专家。该文章会同步在微信公众号 【DevXJava】, 方便在微信客户端阅读。
本章会介绍
AOP
静态通知
和动态通知
,静态通知
很简单是指固定的表达式在编译器就已经确定了,动态通知
的表达式是在每次调用时动态的最终确定的。
场景
public class AopTest {
@Aspect
static class MyAspect {
// 静态通知
@Before("execution(* foo(..))")
public void before1() {
System.out.println("@Aspect @Before1 ------------------------------");
}
// 动态通知
@Before("execution(* foo(..)) && args(x)")
public void before2(int x) {
System.out.println("@Aspect @Before2 ------------------------------ x = " + x);
}
}
static class Target {
public void foo(int x) {
System.out.println("Target foo x = " + x);
}
}
public static void main(String[] args) throws Throwable {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
Logger logger = loggerContext.getLogger(AnnotationAwareAspectJAutoProxyCreator.class);
logger.setLevel(Level.TRACE);
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
AnnotationAwareAspectJAutoProxyCreator proxyCreator = new AnnotationAwareAspectJAutoProxyCreator();
proxyCreator.setBeanFactory(factory);
factory.addBeanPostProcessor(proxyCreator);
factory.registerBeanDefinition("myAspect" , BeanDefinitionBuilder
.genericBeanDefinition(MyAspect.class)
.getBeanDefinition());
// findEligibleAdvisors
Method findEligibleAdvisors = AbstractAdvisorAutoProxyCreator.class.getDeclaredMethod("findEligibleAdvisors", Class.class, String.class);
findEligibleAdvisors.setAccessible(true);
List<Advisor> advisors = (List<Advisor>) findEligibleAdvisors.invoke(proxyCreator, Target.class, "target");
for (Advisor advisor : advisors) {
System.out.println("advisor => " + advisor);
}
Target target = new Target();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetClass(Target.class);
proxyFactory.setTargetSource(new SingletonTargetSource(target));
Object proxy = proxyFactory.getProxy();
List<Object> chain = proxyFactory.getInterceptorsAndDynamicInterceptionAdvice(Target.class.getDeclaredMethod("foo" , int.class), Target.class);
for (Object c : chain) {
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>> " + c);
}
Constructor<ReflectiveMethodInvocation> constructor = ReflectiveMethodInvocation.class.getDeclaredConstructor(Object.class, Object.class, Method.class, Object[].class, Class.class, List.class);
constructor.setAccessible(true);
ReflectiveMethodInvocation invocation = constructor.newInstance(proxy , target ,
Target.class.getDeclaredMethod("foo" , int.class) , new Object[]{666} , Target.class , chain);
invocation.proceed();
}
}
动态通知 InterceptorAndDynamicMethodMatcher
确定动态通知
DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice
方法内会根据MethodMatcher
判断切面是否为动态通知。
ReflectiveMethodInvocation#proceed
DevX
会持续分享 Java
技术干货,如果你觉得本文对你有帮助希望你可以分享给更多的朋友看到。该文章会同步在微信公众号 【DevXJava】, 方便在微信客户端阅读。
DevX 不止于技术