我有以下弹簧配置:
<context:component-scan base-package="uk.co.mysite.googlecontactsync.aop"/>
<bean name="simpleEmailSender" class="uk.co.mysite.util.email.simple.SimpleEmailSenderImplementation"/>
<aop:aspectj-autoproxy/>
然后我有一个方面:
@Aspect
public class SyncLoggingAspect {
@Autowired
private SimpleEmailSender simpleEmailSender
@AfterReturning(value="execution(* uk.co.mysite.datasync.polling.Poller+.doPoll())", returning="pusher")
public void afterPoll(Pusher pusher) {
simpleEmailSender.send(new PusherEmail(pusher));
}
}
此方面有效(我可以在afterPoll上点击断点)但simpleEmailSender为null。不幸的是,我找不到明确的文件说明原因。 (为了记录,我的simpleEmailSender bean存在并正确连接到其他类)以下事情使我感到困惑:
显然你可以告诉我,我不了解事情应该如何从头开始。
答案 0 :(得分:33)
方面是单个对象,在Spring容器外部创建。使用XML配置的解决方案是使用Spring的工厂方法来检索方面。
<bean id="syncLoggingAspect" class="uk.co.demo.SyncLoggingAspect"
factory-method="aspectOf" />
使用此配置,该方面将被视为任何其他Spring bean,并且自动装配将正常工作。
您还必须在Enum对象和其他对象上使用factory-method,而不使用构造函数或在Spring容器外部创建的对象。
答案 1 :(得分:18)
另一种选择是将@Configurable
添加到方面类,而不是乱用XML。
答案 2 :(得分:8)
对于Spring Boot使用@Autowired和AspectJ,我找到了以下方法。 在配置类中添加您的方面:
@Configuration
@ComponentScan("com.kirillch.eqrul")
public class AspectConfig {
@Bean
public EmailAspect theAspect() {
EmailAspect aspect = Aspects.aspectOf(EmailAspect.class);
return aspect;
}
}
然后,您可以在方面类中成功自动装配服务:
@Aspect
public class EmailAspect {
@Autowired
EmailService emailService;
答案 3 :(得分:4)
仅使用java配置配置@Autowired(因此,没有基于XML的配置)需要一些额外的工作,而不仅仅是向类中添加@Configuration,因为它还需要aspectOf方法。
对我有用的是创建一个新类:
@Component
public class SpringApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
然后在使用@DependsOn @Configured和@Autowired:
的方面使用它@DependsOn("springApplicationContextHolder")
@Configuration
@Aspect
public class SomeAspect {
@Autowired
private SomeBean someBean;
public static SomeAspect aspectOf() {
return SpringApplicationContextProvider.getApplicationContext().getBean(SomeAspect.class);
}
需要@DependsOn,因为spring无法确定依赖项,因为bean是静态使用的。
答案 4 :(得分:4)
我没有50位代表对某个问题发表评论,所以这是另一个与@ Jitendra Vispute答案相关的答案。 春季官方文件提到:
您可以在Spring XML配置中将方面类注册为常规bean,或者通过类路径扫描自动检测它们 - 就像任何其他Spring管理的bean一样。但是,请注意@Aspect注释不足以在类路径中自动检测:为此,您需要添加单独的@Component注释(或者根据Spring的组件扫描程序的规则添加符合条件的自定义构造型注释)。 Source: Spring '4.1.7.Release' documentation
这意味着添加@Component注释并在Configuration上添加@ComponentScan会使@Jitendra Vispute的示例工作。对于春季启动aop样本它工作,虽然我没有搞乱上下文刷新。Spring boot aop sample:
<强>应用强>:
package sample.aop;
@SpringBootApplication
public class SampleAopApplication implements CommandLineRunner {
// Simple example shows how an application can spy on itself with AOP
@Autowired
private HelloWorldService helloWorldService;
@Override
public void run(String... args) {
System.out.println(this.helloWorldService.getHelloMessage());
}
public static void main(String[] args) throws Exception {
SpringApplication.run(SampleAopApplication.class, args);
}
}
应用程序也应该作为普通的Spring Framework应用程序运行,并带有以下注释而不是@SpringBootApplication:
和AnnotationConfigApplicationContext而不是SpringApplication。
<强>服务强>:
package sample.aop.service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class HelloWorldService {
@Value("${name:World}")
private String name;
public String getHelloMessage() {
return "Hello " + this.name;
}
}
监控方面:
package sample.aop.monitor;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class ServiceMonitor {
@AfterReturning("execution(* sample..*Service.*(..))")
public void logServiceAccess(JoinPoint joinPoint) {
System.out.println("Completed: " + joinPoint);
}
}
答案 5 :(得分:2)
这blog post解释得非常好。由于在弹簧容器外部创建了方面单例,因此您需要使用仅在AspectJ(而非Spring AOP)编织后才能使用的factory-method =“aspectOf”:
注意factory-method =“aspectOf”告诉Spring使用真实的 AspectJ(不是Spring AOP)方面创建这个bean。那之后 在这方面编织它有一个 “aspectOf”方法。
那样:
找不到匹配的工厂方法:工厂方法'aspectOf()' - 那 意味着这个方面不是由AspectJ weaver编织的。
根据我对spring 3.1的经验,如果我不使用@Autowired但传统的setter用于依赖注入,它会被注入并按预期工作而不使用aspectJ weaver。虽然我遇到问题的方面是单身...它导致'perthis'实例化模型。
答案 6 :(得分:2)
将@Component添加到aspect类,并且应该自动注入依赖项。 并添加上下文:component-scan for package,其中aspect在spring上下文文件中。
@Component
@Aspect
public class SomeAspect {
/* following dependency should get injected */
@Autowired
SomeTask someTask;
/* rest of code */
}
答案 7 :(得分:0)
使用编译时编织,请参阅:https://github.com/avner-levy/minimal_spring_hibernate_maven_setup/blob/master/pom.xml
中的插件示例由于Tobias / Willie / Eric的上述说明,以下注释和Spring配置组合适用于我:
类别:
package com.abc
@Configurable
@Aspect
public class MyAspect {
@Autowired
protected SomeType someAutoWiredField;
}
XML:
<context:spring-configured />
<context:component-scan base-package="com.abc" />
答案 8 :(得分:0)
@Configurable(autowire = Autowire.BY_TYPE)
将此注释添加到您的Aspectj
类中。然后它将由Spring IOC处理。
答案 9 :(得分:0)
对于在@Aspect 中使用@Autowired 的Spring Boot, 我的方法是使用 spring.factories 配置文件
在 src/main/resources 中创建一个名为 spring.factories 的文件
文件内容如下
org.springframework.boot.autoconfigure.EnableAutoConfiguration=pack.age.to.YourAspect,pack.age.to.YourDAO