我有以下Spring配置:
<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为空。 不幸的是我找不到为什么这是明确的文件。 (根据记录,我simpleEmailSender豆存在并正确连接到其他类)下面的事情让我困惑:
- 与上下文:组件扫描应该是捡@Aspect? 如果是,那么这无疑将是一个春季管理的bean,从而自动连接应该工作?
- 如果上下文:组件扫描不用于创建方面,怎么我的方面正在创建? 我认为AOP:AspectJ的自动代理只是创建了BeanPostProcessor来代理我的@Aspect类? 这将如何做到这一点,如果它不是一个Spring管理豆?
很明显,你可以告诉我没有的东西怎么应该从底层开始工作的理解。
Answer 1:
方面是一个单独的对象,并且Spring容器之外创建。 使用XML配置的解决方案是使用Spring的工厂方法来检索方面。
<bean id="syncLoggingAspect" class="uk.co.demo.SyncLoggingAspect"
factory-method="aspectOf" />
利用这种配置方面将被视为任何其他Spring bean和自动装配将恢复正常。
你也必须使用原厂方法对枚举对象和其他对象,而被Spring容器之外创建一个构造函数或对象。
Answer 2:
另一种选择是增加@Configurable
到您的方面类,而不是用XML乱搞的。
Answer 3:
春季启动到@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;
Answer 4:
我没有50代表对一个问题所以这里的评论是另一个答案与@ Jitendra Vispute答案。 官方春天文档中提到:
你可以注册方面类作为普通豆在Spring XML配置,或自动检测他们通过使用classpath扫描 - 就像任何其他的Spring管理的bean。 但是,请注意@Aspect注解不足以在classpath中自动检测:为了这个目的,你需要添加一个单独的@Component注释(或可选择地有资格,按照Spring的组件扫描仪的规则自定义构造型注解)。 来源:春秋“4.1.7.Release”文档 。
这将意味着增加一个@Component注释并添加@ComponentScan您的配置将使@Jitendra Vispute的例子工作。 对于春季启动AOP品尝它的工作,虽然我与上下文刷新没有周围的混乱。 春天开机AOP样本 :
应用 :
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);
}
}
该应用程序还应该运行与以下注释,而不是@SpringBootApplication纯Spring框架的应用:
- @组态
- @EnableAspectJAutoProxy
- @ComponentScan
和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);
}
}
Answer 5:
配置@Autowired与Java的配置只(所以没有基于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春天不能确定,因为该bean staticly使用的依赖。
Answer 6:
本博客文章解释了它真的很好。 由于这方面的单身是Spring容器之外创建你需要用factory-method =” aspectOf”它是由AspectJ的(不是Spring AOP)编织后才可用:
通知工厂方法=” aspectOf”告诉Spring使用一个真正的AspectJ(不是Spring AOP)方面创造这个bean。 使后方面被编织在它有一个“aspectOf”的方法。
以便 :
没有匹配工厂方法发现:工厂方法“aspectOf()” - 这将意味着该方面不是由AspectJ织入机织。
从我与春天3.1的经验,如果我不使用@Autowired但对于依赖注入传统的二传手,它被注入预期不AspectJ织入工作。 虽然我现在遇到所述方面是单身问题...这会导致“perthis”实例模型。 。
Answer 7:
添加@Component对方面类和你的依赖应该得到自动注入。 并添加背景:组件扫描程序包在您的方面是在Spring上下文文件。
@Component
@Aspect
public class SomeAspect {
/* following dependency should get injected */
@Autowired
SomeTask someTask;
/* rest of code */
}
Answer 8:
使用编译时织,看到在插件例如: https://github.com/avner-levy/minimal_spring_hibernate_maven_setup/blob/master/pom.xml
感谢以下注释和Spring配置的组合适用于我的笔记上面由Tobias /威利/埃里克:
类:
package com.abc
@Configurable
@Aspect
public class MyAspect {
@Autowired
protected SomeType someAutoWiredField;
}
XML:
<context:spring-configured />
<context:component-scan base-package="com.abc" />
Answer 9:
@Configurable(autowire = Autowire.BY_TYPE)
这个注释添加到您Aspectj
类。 然后,它会由Spring IOC处理。
文章来源: Spring autowired bean for @Aspect aspect is null