在使用SpringAOP 且新建了InstantiationAwareBeanPostProcessor实现类报错问题
springAOP 的循环引用的问题
在阅读spring源码的时候很好奇InstantiationAwareBeanPostProcessor的作用,所以自己新建了一个实现类,但是在之前我已经把整个包里面的类都进行了AOP,运行的时候很蠢的出现了一个循环引用的问题,因此记录一下这个问题。
InstantiationAwareBeanPostProcessor的作用
在调用Bean的构造器进行初始话的时候会调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation、
postProcessAfterInstantiation两个方法。
测试:
准备一个实体Bean,OrderService
@Component
public class OrderService implements ApplicationContextAware, ApplicationListener, BeanNameAware {
private ApplicationContext context;
private String beanName;
public OrderService(){
System.out.println("无参构造器OrderService");
}
@Autowired
public UserService userService;
public String getHello(){
return "hello";
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// 获取Aware接口获取上下文
System.out.println("获取Aware接口获取上下文");
this.context = applicationContext;
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("监听到了一个感兴趣的事情" + event.getClass());
}
public void getMethod(){
System.out.println("getBeanName"+ this.beanName);
System.out.println("Method==========");
}
@Override
public void setBeanName(String name) {
this.beanName = name;
}
}
准备一个InstantiationAwareBeanPostProcessor的实现类
@Component
public class TestInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("TestInstantiationAwareBeanPostProcessor---------postProcessBeforeInstantiation1");
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("TestInstantiationAwareBeanPostProcessor---------postProcessAfterInstantiation2");
return false;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.println("TestInstantiationAwareBeanPostProcessor---------postProcessProperties3");
return null;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("TestInstantiationAwareBeanPostProcessor---------postProcessBeforeInitialization4");
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("TestInstantiationAwareBeanPostProcessor---------postProcessAfterInitialization5");
return null;
}
}
运行main方法
public class MyFirstSpringApplication {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
OrderService orderService = (OrderService) context.getBean("orderService");
System.out.println("====================orderServiceBefore");
System.out.println(orderService.getHello());
System.out.println("====================orderServiceAfter");
}
}
结果:
TestInstantiationAwareBeanPostProcessor---------postProcessBeforeInstantiation1
无参构造器OrderService
TestInstantiationAwareBeanPostProcessor---------postProcessAfterInstantiation2
从结果中可以看出 两个方法是在调用构造参数的前后进行执行的
突然间很好奇,如果加上AOP会是什么效果
因此,就在项目中引入了一个AOP的测试代码
package com.tanxii.service.test.aspects;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyFirstAspectjs {
@Pointcut("execution(* com.tanxii.service.test.*.*(..))")
public void pointCut(){
}
@Before("pointCut()")
public void before(JoinPoint jp){
System.out.println(jp.getSignature().getName());
System.out.println("===============before");
}
@After("pointCut()")
public void after(JoinPoint jp){
System.out.println(jp.getSignature().getName());
System.out.println("================after");
}
@Around("pointCut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("================beforeAround");
Object proceed = pjp.proceed();
System.out.println(proceed);
System.out.println("================afterAround");
return proceed;
}
}
问题所在
如果我将TestInstantiationAwareBeanPostProcessor这个类的包路径放在AOP中pointCut指定的包扫描路径下,运行的时候会出现Is there an unresolvable circular reference 报错,原因是在运行的时候TestInstantiationAwareBeanPostProcessor已经被AOP了,生成了一个CGLIB代理生成的对象,然后执行postProcessBeforeInstantiation方法的时候,走AOP方法的时候使得MyFirstAspectjs这个Bean也被代理了。最后出现自己调用自己的方法,然后自己又是一个代理类,导致了一个无限循环的问题。
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'myFirstAspectjs': Requested bean is currently in creation: Is there an unresolvable circular reference?
记录一下产生错误的源码位置:
this.aspectJAdviceMethod
this.aspectInstanceFactory.getAspectInstance()
这两个的值都是myFirstAspectjs对象,导致自己执行自己代理的实例方法,这里出现了循环执行,导致报错信息
总结: 在项目中如果需要实现InstantiationAwareBeanPostProcessor这个接口的方法,必须要把这个类要放在AOP指定范围之外,不然就会报错