代理创建器
点击查看代码
package org.springframework.aop.framework.autoproxy;
// 包名与 AnnotationAwareAspectJAutoProxyCreator 一致,方便调用方法。
import org.aopalliance.intercept.MethodInterceptor;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import java.util.List;
public class S16 {
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("s16Aspect", S16Aspect.class);
context.registerBean("s16Config", S16Config.class);
context.registerBean(ConfigurationClassPostProcessor.class);
context.registerBean(AnnotationAwareAspectJAutoProxyCreator.class);
context.refresh();
// for (String beanDefinitionName : context.getBeanDefinitionNames()) {
// System.out.println(beanDefinitionName);
// }
/*AnnotationAwareAspectJAutoProxyCreator 的作用 是一个 BeanPostProcessor
将高级 @Aspect 切面统一为低级 Advisor 切面
在合适的时机创建代理
创建 -> (*) 依赖注入 -> 初始化 (*)
为了方便测试将包名改成了其所在包。*/
AnnotationAwareAspectJAutoProxyCreator proxyCreator
= context.getBean(AnnotationAwareAspectJAutoProxyCreator.class);
//第一个重要方法 findEligibleAdvisors 找到有【资格】的 Advisors
//* 有【资格】的 Advisor 一部分是低级的, 可以由自己编写, 如本例 S16 中的 advisor3
//* 有【资格】的 Advisor 另一部分是高级的, 由解析 @Aspect 后获得
List<Advisor> advisors = proxyCreator.findEligibleAdvisors(S16Bean1.class, "s16Bean1");
// for (Advisor advisor : advisors) {
// System.out.println(advisor);
// }
// 第二个重要方法 wrapIfNecessary
//* 它内部调用 findEligibleAdvisors, 只要返回集合不空, 则表示需要创建代理
//* 它的调用时机通常在原始对象初始化后执行, 但碰到循环依赖会提前至依赖注入之前执行
S16Bean1 s16Bean1 = new S16Bean1();
Object o1 = proxyCreator.wrapIfNecessary(s16Bean1, "s16Bean1", "s16Bean1");
// System.out.println(o1.getClass().getSimpleName());
Object o2 = proxyCreator.wrapIfNecessary(new S16Bean2(), "s16Bean2", "s16Bean2");
// System.out.println(o2.getClass().getSimpleName());
((S16Bean1) o1).s16B();
}
}
class S16Bean1 {
public void s16A() {
System.out.println("s16A running1...");
}
public void s16B() {
System.out.println("s16B running1...");
}
}
class S16Bean2 {
public void s16A2() {
System.out.println("s16A running2...");
}
public void s16B2() {
System.out.println("s16B running2...");
}
}
@Aspect
class S16Aspect{
@Before("execution(* s16B())")
public void s16Advice1() {
System.out.println("s16Advice1 before...");
}
@After("execution(* s16A())")
public void s16Advice2() {
System.out.println("s16Advice2 after...");
}
}
@Configuration
class S16Config {
@Bean("s16Advisor")
public Advisor advisor(MethodInterceptor s16Advice3) {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* s16B())");
return new DefaultPointcutAdvisor(pointcut,s16Advice3);
}
@Bean
public MethodInterceptor s16Advice3() {
return invocation -> {
System.out.println("s16Advice3 before...");
Object result = invocation.proceed();
System.out.println("s16Advice3 after...");
return result;
};
}
}
- AnnotationAwareAspectJAutoProxyCreator 的作用
- 将高级 @Aspect 切面统一为低级 Advisor 切面
- 在合适的时机创建代理
- findEligibleAdvisors 找到有【资格】的 Advisors
- 有【资格】的 Advisor 一部分是低级的, 可以由自己编写, 如本例 S16 中的 advisor3
- 有【资格】的 Advisor 另一部分是高级的, 由解析 @Aspect 后获得
- wrapIfNecessary
- 它内部调用 findEligibleAdvisors, 只要返回集合不空, 则表示需要创建代理
- 它的调用时机通常在原始对象初始化后执行, 但碰到循环依赖会提前至依赖注入之前执行
代理创建时机
点击查看代码
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean(ConfigurationClassPostProcessor.class);
context.registerBean(Config.class);
context.refresh();
context.close();
// 创建 -> (*) 依赖注入 -> 初始化 (*)
/*
学到了什么
a. 代理的创建时机
1. 初始化之后 (无循环依赖时)
2. 实例创建后, 依赖注入前 (有循环依赖时), 并暂存于二级缓存
b. 依赖注入与初始化不应该被增强, 仍应被施加于原始对象
*/
}
@Configuration
static class Config {
@Bean // 解析 @Aspect、产生代理
public AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator() {
return new AnnotationAwareAspectJAutoProxyCreator();
}
@Bean // 解析 @Autowired
public AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor() {
return new AutowiredAnnotationBeanPostProcessor();
}
@Bean // 解析 @PostConstruct
public CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor() {
return new CommonAnnotationBeanPostProcessor();
}
@Bean
public Advisor advisor(MethodInterceptor advice) {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* foo())");
return new DefaultPointcutAdvisor(pointcut, advice);
}
@Bean
public MethodInterceptor advice() {
return (MethodInvocation invocation) -> {
System.out.println("before...");
return invocation.proceed();
};
}
@Bean
public Bean1 bean1() {
return new Bean1();
}
@Bean
public Bean2 bean2() {
return new Bean2();
}
}
static class Bean1 {
public void foo() {
}
public Bean1() {
System.out.println("Bean1()");
}
@Autowired public void setBean2(Bean2 bean2) {
System.out.println("Bean1 setBean2(bean2) class is: " + bean2.getClass());
}
@PostConstruct public void init() {
System.out.println("Bean1 init()");
}
}
static class Bean2 {
public Bean2() {
System.out.println("Bean2()");
}
@Autowired public void setBean1(Bean1 bean1) {
System.out.println("Bean2 setBean1(bean1) class is: " + bean1.getClass());
}
@PostConstruct public void init() {
System.out.println("Bean2 init()");
}
}
}
- 代理的创建时机
- 初始化之后 (无循环依赖时)
- 实例创建后, 依赖注入前 (有循环依赖时), 并暂存于二级缓存
- 循环依赖,A 中要依赖注入 B,B 中要注入 A
- 依赖注入与初始化不应该被增强, 仍应被施加于原始对象
- 高级切面利用 @Order 注解可以设置通知的优先级,值越小优先级越高,低级切面可以通过 setOrder 方法来设置值,Order 加在方法和 @Bean 上不生效。
点击查看代码
@Aspect
@Order(2) //设置 Order 值为2,默认是整数最大值
class S16Aspect{
@Before("execution(* s16B())")
public void s16Advice1() {
System.out.println("s16Advice1 before...");
}
@After("execution(* s16A())")
public void s16Advice2() {
System.out.println("s16Advice2 after...");
}
}
@Configuration
class S16Config {
@Bean("s16Advisor")
public Advisor advisor(MethodInterceptor s16Advice3) {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* s16B())");
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, s16Advice3);
advisor.setOrder(1); //设置 Order 值
return advisor;
}
}
@Before 对应的低级通知
点击查看代码
// 模拟将用注解标注的通知(@Before @After...)转换为低级通知
public class S16Test {
public static void main(String[] args) {
//创建切面的工厂对象
SingletonAspectInstanceFactory factory = new SingletonAspectInstanceFactory(new S16Aspect());
//创建包含低级切面的集合
List<Advisor> advisors = new ArrayList<>();
//利用反射获得高级切面中的所有方法
Method[] methods = S16Aspect.class.getDeclaredMethods();
//遍历方法找到所有含相关注解的方法
for (Method method : methods) {
if (method.isAnnotationPresent(Before.class)) {
//获得其中的切点表达式
String execution = method.getAnnotation(Before.class).value();
//创建切点
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(execution);
//创建通知 前置通知
AspectJMethodBeforeAdvice advice = new AspectJMethodBeforeAdvice(method, pointcut, factory);
//创建低级切面
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
//将切面添加到切面的集合
advisors.add(advisor);
} else if (method.isAnnotationPresent(After.class)) {
//获得其中的切点表达式
String execution = method.getAnnotation(After.class).value();
//创建切点
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(execution);
//创建通知 后置通知
AspectJAfterAdvice advice = new AspectJAfterAdvice(method, pointcut, factory);
//创建低级切面
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
//将切面添加到切面的集合
advisors.add(advisor);
}
}
for (Advisor advisor : advisors) {
System.out.println(advisor);
}
}
@Order(2)
@Aspect
static class S16Aspect {
@Before("execution(* s16B())")
public void s16Advice1() {
System.out.println("s16Advice1 before...");
}
@After("execution(* s16A())")
public void s16Advice2() {
System.out.println("s16Advice2 after...");
}
}
static class S16Bean1 {
public void s16A() {
System.out.println("s16A running1...");
}
public void s16B() {
System.out.println("s16B running1...");
}
}
static class S16Bean2 {
public void s16A2() {
System.out.println("s16A running2...");
}
public void s16B2() {
System.out.println("s16B running2...");
}
}
}
- @Before 前置通知会被转换为原始的 AspectJMethodBeforeAdvice 形式, 该对象包含了如下信息
- 通知代码从哪儿来
- 切点是什么(这里为啥要切点, 后面解释)
- 通知对象如何创建, 本例共用同一个 Aspect 对象
- 类似的还有
- AspectJAroundAdvice (环绕通知)
- AspectJAfterReturningAdvice(返回后通知)
- AspectJAfterThrowingAdvice (异常通知)
- AspectJAfterAdvice (后置通知)