经常出现启动时出现循环依赖异常
创新互联于2013年开始,先为义马等服务建站,义马等地企业,进行企业商务咨询服务。为义马企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'taskPunchEvent': Injection of resource dependencies failed; nested exception is org.
springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'playContentService': Bean with name 'playContentService' has been injected into other be
ans [toVoConvertor] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. Thi
s is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:325)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1404)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1255)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1175)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:595)
... 40 more
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'playContentService': Bean with name 'playContentService' has been injecte
d into other beans [toVoConvertor] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version o
f the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:622)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeanByName(AbstractAutowireCapableBeanFactory.java:452)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:527)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:497)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:637)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:180)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:322)
... 51 more
先不关注其他不规范问题,看现象
注:Spring启动流程与Bean创建初始化流程如不熟悉,自行补习,篇幅原因此处不做介绍
首先,通过spring通过扫描各种注解 @Compoent、@Service、@Configuration等等把需要交给spring管理的bean初始化成 BeanDefinition 的列表
然后,根据 BeanDefinition 创建spring bean的实例
并非使用者手动去getBean才会加载并初始化,而是框架启动时进行加载
Spring创建Bean - #DefaultListableBeanFactory#preInstantiateSingletons
@Override
public void preInstantiateSingletons() throws BeansException {
//......
List beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
//FactoryBean接口处理
......
}
else {
//正常Bean的加载入口
getBean(beanName);
}
}
}
//......
}
注入的好处很明显,如果容器中不存在或者存在多个实现时,可以从容处理。
强依赖,先有鸡还是先有蛋问题暂无解,此依赖方式Spring不支持,除非自身实现代理加延迟注入,这种方式很难解决,除非实现类似于lazy生成代理方式进行解耦来实现注入,Spring没有支持可能因为此种注入场景都可以用其他方式代替且场景极少。
弱依赖,spring 4.3之后增加 ObjectProvider 来处理
//构造器循环依赖示例
public class StudentA {
private StudentB studentB ;
public StudentA(StudentB studentB) {
this.studentB = studentB;
}
}
public class StudentB {
private StudentA studentA ;
public StudentB(StudentA studentA) {
this.studentA = studentA;
}
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//属性注入
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
DefaultSingletonBeanRegistry
private final Map singletonObjects = new ConcurrentHashMap<>(256);
二级缓存(未初始化未填充属性提前暴露的Bean)
private final Map earlySingletonObjects = new HashMap<>(16);
三级缓存(Bean创建时提供代理机会的Bean工厂缓存)
private final Map> singletonFactories = new HashMap<>(16);
循环依赖产生在Bean创建时
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
BeanWrapper instanceWrapper = null;
if (instanceWrapper == null) {
//创建Bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
.....
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
//填充Bean依赖与Bean的初始化
Object exposedObject = bean;
try {
//填充依赖的bean实例
populateBean(beanName, mbd, instanceWrapper);
//初始化---注意!注意!注意!此方法中可能调用 BeanPostProcessor
//的applyBeanPostProcessorsAfterInitialization时可能会返回代理对象,如果代理途径与创建时代理方式不同则也会产生不同代理对象
//从而产生循环依赖中对象不一致情况
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
//如果存在循环依赖,则保证最开始创建的Bean需要是循环依赖 getEarlyBeanReference触发生成的bean
//因为getEarlyBeanReference 可能返回的是代理类,因为singleton必须全局唯一
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
//只有真正存在循环依赖时,才会触发 getEarlyBeanReference调用产生EarlyBean
//未存在循环依赖,则getEarlyBeanReference不触发,earlySingletonReference为null,返回exposedObject即可
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
......
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
return exposedObject;
}
三级缓存获取Bean
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//一级缓存(单例池)获取Bean
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//二级缓存获取(提前暴露不完全)Bean
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//三级缓存Bean的创建工厂获取bean(可提前被代理)
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
SmartInstantiationAwareBeanPostProcessor重点 -> APC之父
//提供提前创建并返回代理的工厂singletonFactory.getObject()执行的是个回调
//addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//getEarlyBeanReference是SmartInstantiationAwareBeanPostProcessor接口定义方法,
//此方法很关键(构造函数推断也在此定义)
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
通俗解释(省略很多细节):A -> B -> C -> A
6.1. 最终原因就是提前暴露的已经注入到C中的A(无论是否被代理)与后来经过初始化后被代理的A(proxy2)不再是同一个Bean;
6.2. 因为Spring管理Bean默认是Singleton的,现在出现了两个bean,默认情况下无法决断,因此就抛出了异常。
spring默认保证一个容器中只能有一个Aop的APC,如过手动添加或者自定义会出现多个APC情况
三者有就按照优先级覆盖,否则就注册一个,因此始终就只会有一个APC
AopConfigUtils
static {
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}
private static BeanDefinition registerOrEscalateApcAsRequired(
Class> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
//因为三个APC存在能力父子关系,按照指定注册的APC自动调整优先级,从而保证只存在一个APC
//如未指定APC,则默认为InfrastructureAdvisorAutoProxyCreator
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
存在多个APC时,如存在循环依赖,此时触发之前放入三级缓存逻辑
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
从而触发多个APC的 getEarlyBeanReference
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
//此时如存在多个APC,则依次执行 getEarlyBeanReference 返回多层代理对象
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
最终proxy2会被注入到依赖的Bean中,即例如:A-proxy2 注入到 B中
存在多个多层代理情况,getEarlyBeanReference 没有问题,但是执行到初始化时
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
//注意这个Bean可是原始对象,每个APC都缓存自身代理过的类,但是存在多个APC时,后续的APC缓存的确是代理类的代理
//即如第二个APC是BeanNameAutoProxyCreator,其缓存的可是 proxy1的class,原始类在此APC是没被代理过的,
//因此此时会对原始类进行二次代理,产生Proxy3
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
//视线返回本次循环依赖最初实例化的结点:A->B->C->A,则此处为A的创建流程
//此时A 通过 getEarlyBeanReference生成A ->proxy2注入到C中,
//C直接实例创建不会触发getEarlyBeanReference,注入到B中
//B直接实例创建不会触发getEarlyBeanReference,注入到A中
//A依赖处理完毕,继续初始化 initializeBean流程 -> postProcessAfterInitialization,返回 proxy3
if (earlySingletonExposure) {
//此时获取到的代理类是 proxy2,即已经注入到依赖类C中的代理,因此不为null
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
//多APC时,exposedObject 在之前initializeBean -> postProcessAfterInitialization作用下返回proxy3
//proxy3 != bean 不一致,违反了singletion原则,因此会抛出循环依赖异常
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
......
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
SmartInstantiationAwareBeanPostProcessor
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
//提前通过singletonFactory.getObject()创建的代理缓存起来以后,这里如果再次判断需要代理,
//缓存中存在已被代理则直接返回原始bean,无需再次代理,后续直接获取earlySingletonReference,
//因此前后代理出来的对象是一致的
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
DefaultListableBeanFactory#resolveDependency
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
......
else {
//处理@lazy
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
ContextAnnotationAutowireCandidateResolver#getLazyResolutionProxyIfNecessary
public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) {
return (isLazy(descriptor) ? buildLazyResolutionProxy(descriptor, beanName) : null);
}
ContextAnnotationAutowireCandidateResolver#isLazy
//是否为@lazy,如果为@lazy则创建依赖代理
protected boolean isLazy(DependencyDescriptor descriptor) {
for (Annotation ann : descriptor.getAnnotations()) {
Lazy lazy = AnnotationUtils.getAnnotation(ann, Lazy.class);
if (lazy != null && lazy.value()) {
return true;
}
}
.......
}
import org.junit.Test;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.env.Environment;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
/**
* @author: Superizer
*/
@Component
public class MainSpringCircularDependencyTester
{
@Test
public void springCircularDependencyTest()
{
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringCircularDependencyConfig.class);
X x = ac.getBean(X.class);
System.out.println("Spring bean X =" + x.getClass().getName());
x.display();
Y y = ac.getBean(Y.class);
System.out.println("Spring bean Y =" + y.getClass().getName());
y.display();
Z z = ac.getBean(Z.class);
System.out.println("Spring bean Z =" + z.getClass().getName());
z.display();
System.out.println("******************Main********************");
}
@Configuration
@ComponentScan("com.myself.demo.spring.v5.circular.dependency")
// @EnableAspectJAutoProxy
@ConditionalOnClass(PersistenceExceptionTranslationPostProcessor.class)
static class SpringCircularDependencyConfig{
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "spring.dao.exceptiontranslation", name = "enabled",
matchIfMissing = true)
public static PersistenceExceptionTranslationPostProcessor
persistenceExceptionTranslationPostProcessor(Environment environment) {
PersistenceExceptionTranslationPostProcessor postProcessor = new PersistenceExceptionTranslationPostProcessor();
boolean proxyTargetClass = environment.getProperty(
"spring.aop.proxy-target-class", Boolean.class, Boolean.TRUE);
postProcessor.setProxyTargetClass(proxyTargetClass);
return postProcessor;
}
}
abstract static class A {
public abstract A injectSources();
public abstract A self();
public void display(){
System.out.println("injectSources:" + injectSources().getClass().getName());
System.out.println("*******************************************************");
}
}
//X、Y、Z 只要循环依赖中第一个类X有注解@Repository,就会出现循环依赖异常
//执行X的singletonFactory.getObject()返回的原对象,但是后边初始化时
//执行到PersistenceExceptionTranslationPostProcessor时单独创建代理逻辑返回的是代理类
//exposedObject = initializeBean(beanName, exposedObject, mbd);
@Repository
// @Component
static class X extends A{
@Resource
private Y y;
@Override
public Y injectSources()
{
return y;
}
@Override
public X self() {
return this;
}
}
@Component
// @Repository
static class Y extends A{
@Resource
private Z z;
@Override
public Z injectSources() {
return z;
}
@Override
public Y self()
{
return this;
}
}
@Component
// @Repository
static class Z extends A{
@Resource
private X x;
@Override
public X injectSources()
{
return x;
}
@Override
public Z self()
{
return this;
}
}
}
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.junit.Test;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.aop.support.AbstractExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Arrays;
/**
* @author: Superizer
* Copyright (C) 2021
* All rights reserved
*/
@Component
public class MainSpringCircularDependencyV2Tester
{
@Test
public void circularDependencyV2Tester()
{
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringCircularDependencyConfig.class);
A a = ac.getBean(A.class);
System.out.println("Spring bean A =" + a.getClass().getName());
a.display();
B y = ac.getBean(B.class);
System.out.println("Spring bean B =" + y.getClass().getName());
y.display();
C z = ac.getBean(C.class);
System.out.println("Spring bean C =" + z.getClass().getName());
z.display();
System.out.println("******************Main********************");
}
@Configuration
@ComponentScan("com.myself.demo.spring.v5.circular.dependency.v2")
@EnableAspectJAutoProxy
static class SpringCircularDependencyConfig {
@Bean
public DefaultPointcutAdvisor defaultPointcutAdvisor() {
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
Pointcut pointcut = new AbstractExpressionPointcut() {
@Override
public ClassFilter getClassFilter() {
return (tmp) -> {
String name = tmp.getName();
if(name.equals(A.class.getName())) {
return true;
}
return false;
};
}
@Override
public MethodMatcher getMethodMatcher() {
return MethodMatcher.TRUE;
}
};
advisor.setPointcut(pointcut);
advisor.setAdvice(new SpringAopAroundMethod());
advisor.setOrder(0);
return advisor;
}
@Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
BeanNameAutoProxyCreator apc = new BeanNameAutoProxyCreator();
apc.setBeanNames("a");
apc.setOrder(-1);
apc.setProxyTargetClass(true);
return apc;
}
}
abstract static class G {
public abstract G injectSources();
public abstract G self();
public void display(){
System.out.println("injectSources:" + injectSources().getClass().getName());
System.out.println("*******************************************************");
}
}
@Component(value = "a")
static class A extends G {
@Resource
private B b;
@Override
public B injectSources()
{
return b;
}
@Override
public A self() {
return this;
}
}
@Component
static class B extends G {
@Resource
private C c;
@Override
public C injectSources() {
return c;
}
@Override
public B self()
{
return this;
}
}
@Component
static class C extends G {
@Resource
private A a;
@Override
public A injectSources()
{
return a;
}
@Override
public C self()
{
return this;
}
}
static class SpringAopAroundMethod implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("Aop Before method!");
try {
Object result = methodInvocation.proceed();
System.out.println("Aop after method!");
return result;
} catch (IllegalArgumentException e) {
System.out.println("Aop throw exception!");
throw e;
}
}
}
}
出现循环依赖其实反映代码结构设计上的问题,理论上应当将循环依赖进行分层,抽取公共部分,然后由各个功能类再去依赖公共部分。
但是在复杂代码中,各个service、manager类互相调用太多,总会一不小心出现一些类之间的循环依赖的问题。可有时候我们又发现在用Spring进行依赖注入时,虽然Bean之间有循环依赖,但是代码本身却大概率能很正常的work,似乎也没有任何bug。
很多敏感的同学心里肯定有些犯嘀咕,循环依赖这种触犯因果律的事情怎么能发生呢?没错,这一切其实都并不是那么理所当然。Spring已经为我们背负了太多,但绝不是偷懒的借口,还是应该规范设计,规范代码,尽量做到从根本上避免这种循环依赖的发生。
本文标题:Spring循环依赖那些事儿(含Spring详细流程图)
转载注明:http://www.mswzjz.cn/qtweb/news41/499241.html
攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能