对于@Aspect方面春天自动装配bean是空(Spring autowired bean for

2019-10-23 17:35发布

我有以下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豆存在并正确连接到其他类)下面的事情让我困惑:

  1. 与上下文:组件扫描应该是捡@Aspect? 如果是,那么这无疑将是一个春季管理的bean,从而自动连接应该工作?
  2. 如果上下文:组件扫描不用于创建方面,怎么我的方面正在创建? 我认为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