Spring aop advice не удалось обработать прокси-сервер, когда bean-компонентон находится в процессе создания - PullRequest
1 голос
/ 16 февраля 2020

Проблема такая же, как и этот вопрос
Я работаю с Spring AOP в аспекте аннотации, один из моих bean-компонентов не может установить совет по аннотации, но другие могут.
Затем я отлаживаю и выяснил причину, код в BeanFactoryAdvisorRetrievalHelper указывает, что если advice bean находится в процессе создания, serviceBean не сможет установить советник.
if (this.beanFactory.isCurrentlyInCreation(name))

public List<Advisor> findAdvisorBeans() {
    // Determine list of advisor bean names, if not cached already.
    String[] advisorNames = this.cachedAdvisorBeanNames;
    if (advisorNames == null) {
        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the auto-proxy creator apply to them!
        advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                this.beanFactory, Advisor.class, true, false);
        this.cachedAdvisorBeanNames = advisorNames;
    }
    if (advisorNames.length == 0) {
        return new ArrayList<>();
    }

    List<Advisor> advisors = new ArrayList<>();
    for (String name : advisorNames) {
        if (isEligibleBean(name)) {
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Skipping currently created advisor '" + name + "'");
                }
            }
            else {
                try {
                    advisors.add(this.beanFactory.getBean(name, Advisor.class));
                }
                catch (BeanCreationException ex) {
                    Throwable rootCause = ex.getMostSpecificCause();
                    if (rootCause instanceof BeanCurrentlyInCreationException) {
                        BeanCreationException bce = (BeanCreationException) rootCause;
                        String bceBeanName = bce.getBeanName();
                        if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
                            if (logger.isTraceEnabled()) {
                                logger.trace("Skipping advisor '" + name +
                                        "' with dependency on currently created bean: " + ex.getMessage());
                            }
                            // Ignore: indicates a reference back to the bean we're trying to advise.
                            // We want to find advisors other than the currently created bean itself.
                            continue;
                        }
                    }
                    throw ex;
                }
            }
        }
    }
    return advisors;
} 

перехватчик

public class DemoInterceptor implements MethodInterceptor {

  @Override
  public Object invoke(MethodInvocation invocation) throws Throwable {
    //do something
    return new Object();
  }

}

Конфигурация советника

config way 1

public class DemoAdvisor implements PointcutAdvisor {

    private MethodInterceptor methodInterceptor;

    private Pointcut pointcut;

    public DemoAdvisor(MethodInterceptor methodInterceptor) {
        this.methodInterceptor = methodInterceptor;
        this.pointcut = new AnnotationMatchingPointcut(null, DemoAnno.class);
    }

    @Override
    public Advice getAdvice() {
        return this.methodInterceptor;
    }

    @Override
    public boolean isPerInstance() {
        return true;
    }

    @Override
    public Pointcut getPointcut() {
        return this.pointcut;
    }
}



@Configuration
public class AnnoAspectConfig {

    @Bean
    public DemoAdvisor DemoAdvisor() {
        DemoAdvisor advisor = new DemoAdvisor(demoInterceptor());
        return advisor;
    }

    @Bean
    public DemoInterceptor demoInterceptor() {
        DemoInterceptor demoInterceptor = new DemoInterceptor();
        return demoInterceptor;
    }

}



Тогда я думаю, что это может быть проблема в конфиге совета, поэтому я изменяю совет конфиг ниже:
config way 2


@Configuration
public class ValidationAdvisor {

    @Bean
    public DefaultPointcutAdvisor demoAdvisor() {
        DemoInterceptor interceptor = new DemoInterceptor();
        AnnotationMatchingPointcut annotationMatchingPointcut = AnnotationMatchingPointcut.forMethodAnnotation(DemoAnno.class);
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
        advisor.setPointcut(annotationMatchingPointcut);
        advisor.setAdvice(interceptor);
        return advisor;
    }

}


Затем все идет поиск, поэтому вопрос, почему config way 1 вызывает сбой установки советника, в то время как config way 2 не сделал

...