qidao123.com技术社区-IT企服评测·应用市场
标题:
spring 18 动态通知调用
[打印本页]
作者:
十念
时间:
2022-8-11 04:04
标题:
spring 18 动态通知调用
带参数绑定的通知方法调用
点击查看代码
@Aspect
static class MyAspect {
@Before("execution(* foo(..))") // 静态通知调用,不带参数绑定,执行时不需要切点
public void before1() {
System.out.println("before1");
}
@Before("execution(* foo(..)) && args(x)") // 动态通知调用,需要参数绑定,执行时还需要切点对象
public void before2(int x) {
System.out.printf("before2(%d)%n", x);
}
}
static class Target {
public void foo(int x) {
System.out.printf("target foo(%d)%n", x);
}
}
@Configuration
static class MyConfig {
@Bean
AnnotationAwareAspectJAutoProxyCreator proxyCreator() {
return new AnnotationAwareAspectJAutoProxyCreator();
}
@Bean
public MyAspect myAspect() {
return new MyAspect();
}
}
public static void main(String[] args) throws Throwable {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean(ConfigurationClassPostProcessor.class);
context.registerBean(MyConfig.class);
context.refresh();
AnnotationAwareAspectJAutoProxyCreator creator = context.getBean(AnnotationAwareAspectJAutoProxyCreator.class);
List<Advisor> list = creator.findEligibleAdvisors(Target.class, "target");
Target target = new Target();
ProxyFactory factory = new ProxyFactory();
factory.setTarget(target);
factory.addAdvisors(list);
Object proxy = factory.getProxy(); // 获取代理
List<Object> interceptorList =
factory.getInterceptorsAndDynamicInterceptionAdvice(Target.class.getMethod(
"foo", int.class), Target.class);
for (Object o : interceptorList) {
showDetail(o);
}
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>");
ReflectiveMethodInvocation invocation = new ReflectiveMethodInvocation(
proxy, target, Target.class.getMethod("foo", int.class),
new Object[]{100}, Target.class, interceptorList
) {}; // spring 内部可以创建匿名子类来创建构造器 protected 的对象
invocation.proceed();
/*
学到了什么
a. 有参数绑定的通知调用时还需要切点,对参数进行匹配及绑定
b. 复杂程度高, 性能比无参数绑定的通知调用低
*/
}
public static void showDetail(Object o) {
try {
Class<?> clazz = Class.forName("org.springframework.aop.framework.InterceptorAndDynamicMethodMatcher");
if (clazz.isInstance(o)) {
Field methodMatcher = clazz.getDeclaredField("methodMatcher");
methodMatcher.setAccessible(true);
Field methodInterceptor = clazz.getDeclaredField("interceptor");
methodInterceptor.setAccessible(true);
System.out.println("环绕通知和切点:" + o);
System.out.println("\t切点为:" + methodMatcher.get(o));
System.out.println("\t通知为:" + methodInterceptor.get(o));
} else {
System.out.println("普通环绕通知:" + o);
}
} catch (Exception e) {
e.printStackTrace();
}
}
复制代码
通过 proxyFactory 的 getInterceptorsAndDynamicInterceptionAdvice() 将其他通知统一转换为 MethodInterceptor 环绕通知
所谓动态通知,体现在上面方法的 DynamicInterceptionAdvice 部分,这些通知调用时因为要为通知方法绑定参数,还需再次利用切点表达式
动态通知调用复杂程度高,性能较低
”匿名子类写法“:
可参考:
https://blog.csdn.net/weixin_39570751/article/details/121253167
点击查看代码
class S18Bean1 {
public S18Bean1() {
}
public void add() {
}
}
复制代码
public class S18Bean2 {
public static void main(String[] args) {
S18Bean1 s18Bean3 = new S18Bean1() {
};
S18Bean1 s18Bean2 = new S18Bean1() {
};
System.out.println(s18Bean3.getClass().getName());
System.out.println(s18Bean2.getClass().getName());
}
}
复制代码
在哪个类创建的就以哪个类开头加$数字再加一个空字符命名,Class类的 getSimpleName() 为空,所以真正的名字是空,是匿名的。点击查看代码
一个包下的字包不属于当前包,当前包中的 protect 成员不能被子包访问。
如果里面有个类有个 protect 修饰的构造器 在子包中访问不了,spring 内部就是通过这个办法创建它的子类调用
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/)
Powered by Discuz! X3.4