实现基于注解的 Spring AspectJ (JavaConfig)
Implementing annotation based Spring AspectJ (JavaConfig)
我们正在尝试将 AspectJ @Aspect
实施到我们现有的软件中,以便在进行服务调用后执行一些代码。
注:
- 我们有服务接口和实现
@Autowired
通过其余控制器以及其他服务实现在整个项目中。
- 这个项目完全是一个 Java 配置,没有任何 XML。
- 我们正在使用 Spring 4.1.2 RELEASE 部署在 Tomcat 7.0.54.
问题:
当我们将 @EnableAspectJAutoProxy
添加到我们的主 @JavaConfig
中时,我们遇到以下异常:
Unresolvable circular reference.
每 @Autowired
次对一长串 beans 的尝试都会失败。
尝试过:
- 删除了
@EnableAspectJAutoProxy
注释,该注释正确地自动装配所有内容,但我们的 @Aspect 永远不会被调用。
- 通过声明在注释中添加了 CGLIB 支持
proxytargetclass=true
无济于事。
- 我们已尝试直接从 Spring 遵循此文档:@EnableAspectJAutoProxy Javadoc
这似乎是 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.)
}
我们正在尝试将 AspectJ @Aspect
实施到我们现有的软件中,以便在进行服务调用后执行一些代码。
注:
- 我们有服务接口和实现
@Autowired
通过其余控制器以及其他服务实现在整个项目中。 - 这个项目完全是一个 Java 配置,没有任何 XML。
- 我们正在使用 Spring 4.1.2 RELEASE 部署在 Tomcat 7.0.54.
问题:
当我们将 @EnableAspectJAutoProxy
添加到我们的主 @JavaConfig
中时,我们遇到以下异常:
Unresolvable circular reference.
每 @Autowired
次对一长串 beans 的尝试都会失败。
尝试过:
- 删除了
@EnableAspectJAutoProxy
注释,该注释正确地自动装配所有内容,但我们的 @Aspect 永远不会被调用。 - 通过声明在注释中添加了 CGLIB 支持
proxytargetclass=true
无济于事。 - 我们已尝试直接从 Spring 遵循此文档:@EnableAspectJAutoProxy Javadoc
这似乎是 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
.
@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.)
}