实现基于注解的 Spring AspectJ (JavaConfig)

Implementing annotation based Spring AspectJ (JavaConfig)

我们正在尝试将 AspectJ @Aspect 实施到我们现有的软件中,以便在进行服务调用后执行一些代码。

注:

问题:

当我们将 @EnableAspectJAutoProxy 添加到我们的主 @JavaConfig 中时,我们遇到以下异常:

Unresolvable circular reference.

@Autowired 次对一长串 beans 的尝试都会失败。

尝试过:

这似乎是 AspectJ 处理自动装配依赖项的代理机制的问题。

为什么我们添加 @EnableAspectJAutoProxy 时会出现这种情况?

我们的 Java 配置:

@Configuration
@EnableWebMvc
@EnableJpaRepositories(basePackages ={"com.company.product.persistence.repository"})
@EnableTransactionManagement
@EnableSwagger
@EnableAspectJAutoProxy
@PropertySource({"classpath:hibernate.properties",
                 "classpath:auth.properties",
                 "classpath:mail.properties",
                 "classpath:locations.properties"
                })
@ComponentScan(basePackages = {"com.company.product"})
public class WebConfig extends WebMvcConfigurerAdapter {
    //Bean declarations here.
    //Note: All services/repos/controllers are annotation based.
}

方面实施:

@Aspect
@Component
public class PostMessageAspect {

private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @After("execution(*com.company.product.persistence.serviceImpl.event.eventServiceImpl.methodCall(..))")
    public void postMessageRun(final JoinPoint joinPoint) {
        logger.info("CALLED AFTER METHOD");
    }
}

更新:

设法让 AOP/AspectJ 在一台开发机器上完美运行,只需要对我们的 Spring 安全配置进行微小的更改。我们都在 Ubuntu 14.0.4 运行 Tomcat 7.0.56 的默认实例上使用 Intellij,openJDK 1.7.0_65。在另一台机器上 运行 相同的软件堆栈,得到以下内容。

堆栈跟踪:

org.springframework.beans.factory.BeanCreationException:创建名称为 'dispatchingMessageController' 的 bean 时出错:注入自动装配的依赖项失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法自动装配字段:com.apx.efm.persistence.service.event.DispatchingEventService com.apx.efm.controllers.message.DispatchingMessageController.dispatchingEventService;嵌套异常是 org.springframework.beans.factory.BeanCreationException:创建名称为 'dispatchingEventServiceImpl' 的 bean 时出错:注入自动装配的依赖项失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法自动装配字段:com.apx.efm.persistence.service.building.BuildingAd dressesService com.apx.efm.persistence.serviceImpl.event.DispatchingEventServiceImpl.buildingAddressesService;嵌套异常是 org.springframework.beans.factory.BeanCreationException:创建名称为 'buildingAddressServiceImpl' 的 bean 时出错:注入自动装配的依赖项失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法自动装配字段:com.apx.efm.persistence.service.building.BuildingService com.apx.efm.persistence.serviceImpl.building.BuildingAddressServiceImpl.buildingService;嵌套异常是 org.springframework.beans.factory.BeanCreationException:创建名称为 'buildingServiceImpl' 的 bean 时出错:注入自动装配的依赖项失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法自动装配字段:com.apx.efm.persistence.service.building.BuildingAddressesService com.apx.efm.persistence.serviceImpl.building.BuildingServiceImpl.buildingAddressesService;嵌套异常是 org.springframework.beans.factory.BeanCreationException:在 class 路径资源 [org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.class] 中定义名称 'methodSecurityInterceptor' 创建 bean 时出错:通过工厂方法实例化 Bean 失败;嵌套异常是 org.springframework.beans.BeanInstantiationException:无法实例化 [org.aopalliance.intercept.MethodInterceptor]:工厂方法 'methodSecurityInterceptor' 抛出异常;嵌套异常是 org.springframework.beans.factory.BeanCreationException:创建名称为 'securityConfig' 的 bean 时出错:注入自动装配的依赖项失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法自动装配字段:private com.apx.efm.persistence.service.user.EfmUserService com.apx.efm.application.config.SecurityConfig.efmUserService;嵌套异常是 org.springframework.beans.factory.BeanCreationException:创建名称为 'efmUserServiceImpl' 的 bean 在文件 [/home/apxdev4/Development/GitRepositories/efim-restful-web-service/target/EFIM/WEB-INF/classes/com/apx/efm/persistence/serviceImpl/user/EfmUserServiceImpl.class] 中定义时出错:bean 初始化失败;嵌套异常是 org.springframework.beans.factory.BeanCurrentlyInCreationException:创建名称为 'methodSecurityInterceptor' 的 bean 时出错:当前正在创建请求的 bean:是否存在无法解析的循环引用?

这完全是我们 Spring 配置的问题。我们的 Spring 安全配置试图 @Autowired bean,而它们仍在由我们的主要应用程序配置处理。我们通过确保在主要 @Configuration.

之后配置 Spring 安全性来解决这个问题
@Override
public void onStartup(ServletContext container) throws ServletException {
    AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
    // Initialize web mvc
    appContext.setDisplayName("APP");
    appContext.register(WebConfig.class);
    appContext.register(SecurityConfig.class);

    // Rest omitted (listeners, dispatcher servlet, etc.)
}