弹簧自动装配bean是空

问题描述:

我有以下Spring配置:弹簧自动装配bean是空

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

  1. 与上下文:组件扫描应该是捡@Aspect?如果它肯定会是一个spring管理bean,那么autowired应该可以工作吗?
  2. 如果上下文:组件扫描不用于创建方面,我的方面是如何创建的?我认为aop:aspectj-autoproxy只是创建一个beanPostProcessor来代理我的@Aspect类?如果它不是一个弹簧管理bean,它会怎么做?

显然你可以告诉我没有理解事情应该如何从头开始工作。

+2

你能还加上'@ Service'旁边'@ Aspect'? – 2012-03-09 12:13:21

+1

它仍然是空的,但我现在收到的信息:预实例中org.s[email protected]76faf7d6单身:定义豆[...,SyncLoggingAspect在日志 – mogronalol 2012-03-09 12:20:31

+0

你尝试加入的二传手SimpleEmailSender ?? – Rocky 2012-03-09 12:38:49

aspect是一个单例对象,它是在Spring容器之外创建的。具有XML配置的解决方案是使用Spring的工厂方法来检索方面。

<bean id="syncLoggingAspect" class="uk.co.demo.SyncLoggingAspect" 
    factory-method="aspectOf" /> 

利用这种构造方面都将被视为任何其他Spring bean和自动装配将工作正常。

您还必须在Enum对象和其他没有构造函数的对象或在Spring容器外创建的对象上使用工厂方法。

+5

从我可以在文档中看到的这是用于使用AspectJ时。我应该使用弹簧AOP。在我的配置中是否有某些东西我缺少/需要添加以使其成为例子? – mogronalol 2012-03-12 09:28:55

+2

想出来后,你确实给我的解决方案,但现在的我,因为我的上述观点仍然感到困惑 – mogronalol 2012-03-12 11:52:19

+0

春天文档是笨重。可配置为非单身人士。 – lwpro2 2014-05-21 01:29:17

另一种选择是将@Configurable添加到您的方面类中,而不是混淆XML。

+2

尼斯。还记得XML中的。 – 2012-06-03 10:28:26

+0

谢谢! '@ Configurable'为我做了诀窍。不需要任何单独的JavaConfig或XML factory-method ='aspect-of'和'@ Configurable'注释。 – 2013-11-29 22:03:58

+0

我刚刚遇到过这种情况,当Spring上下文刷新时,Spring不会自动更新引用。我在http://stackoverflow.com/q/22826526/827480上发布了一个问题,寻找解决这个问题的方法。 – 2014-04-03 02:08:02

blog post解释得很好。由于这方面的单身是Spring容器之外创建你需要用factory-method =” aspectOf”它是通过AspectJ织在后才可用(不是Spring AOP):

通知工厂-method =“aspectOf”告诉Spring使用真实的AspectJ(而不是Spring AOP)方面来创建这个bean。所以 方面编织后有一个 “aspectOf”的方法。

这样:

没有匹配的工厂方法发现:工厂方法 'aspectOf()' - 这 将意味着方面没有被AspectJ织入编织。

从我使用spring 3.1的经验来看,如果我不使用@Autowired而是传统的setter进行依赖注入,它会被注入并按预期工作,没有aspectJ weaver。尽管我在单身方面遇到问题......它导致了'perthis'实例化模型。 。

仅配置java config(因此没有基于XML的配置)配置@Autowired需要一点额外的工作,而不仅仅是将@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是静态使用的。

+0

谢谢你,因为这是我能找到的唯一基于注释的例子。 – mag382 2013-11-07 18:10:31

+0

CheckServicesPermissionsAspect.class?我不明白这是什么。 – sudeepdino008 2014-06-19 09:20:13

+0

这是一个来自现有项目的副本,但我忘了概括这一点,现在修复:) – Wouter 2014-06-19 11:29:05

添加@Component对方面类和你的依赖应该得到自动注入。 并添加背景:组件扫描程序包在您的方面是在Spring上下文文件。

@Component 
@Aspect 
public class SomeAspect { 
    /* following dependency should get injected */ 
    @Autowired 
    SomeTask someTask; 
    /* rest of code */ 
} 
+1

这实际上对我有用。 – dantebarba 2016-12-29 15:05:42

我没有50个代表发表评论,因此这里是另一个与@ Jitendra Vispute答案有关的答案。 官方春天文档中提到:

你可以在你的Spring XML配置寄存器的方面类定期豆类,或通过使用classpath扫描自动检测他们 - 就像任何其他的Spring管理的bean。但是,请注意@Aspect注解不足以在classpath中自动检测:为了这个目的,你需要添加一个单独的@Component注释(或可选择地有资格,按照Spring的组件扫描仪的规则自定义构造型注解)。 Source: Spring '4.1.7.Release' documentation

这将意味着在配置中添加@Component注释并添加@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); 
    } 
} 

该应用程序还应该运行与以下注释,而不是@SpringBootApplication纯Spring框架的应用:

  • @Configuration
  • @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); 
    } 
} 

使用编译时织,看到在插件例如:https://github.com/avner-levy/minimal_spring_hibernate_maven_setup/blob/master/pom.xml

下面的注释和Spring的结合感谢Tobi上面的注释,config对我有用如/威利/埃里克:

类:

package com.abc 
@Configurable 
@Aspect 
public class MyAspect { 
    @Autowired 
    protected SomeType someAutoWiredField; 
} 

XML:

<context:spring-configured /> 
<context:component-scan base-package="com.abc" /> 

春天开机使用@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;