Spring自动assembly使用@Configurable

我玩的想法是使用Spring @Configurable@Autowire将DAO注入到域对象中,以便它们不需要直接了解持久层。

我试图按照http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-atconfigurable ,但我的代码似乎没有效果。

基本上,我有:

 @Configurable public class Artist { @Autowired private ArtistDAO artistDao; public void setArtistDao(ArtistDAO artistDao) { this.artistDao = artistDao; } public void save() { artistDao.save(this); } } 

和:

 public interface ArtistDAO { public void save(Artist artist); } 

 @Component public class ArtistDAOImpl implements ArtistDAO { @Override public void save(Artist artist) { System.out.println("saving"); } } 

在application-context.xml中,我有:

 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springsource.org/dtd/spring-beans-2.0.dtd"> <beans> <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" /> <bean class="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect" factory-method="aspectOf"/> </beans> 

类path扫描和初始化由Play的弹簧模块执行! 框架,虽然其他autowired豆的工作,所以我敢肯定,这不是根本原因。 我使用的是Spring 3.0.5。

在其他代码中(在使用Spring注入到我的控制器的bean中的一个方法中,实际上),我这样做:

 Artist artist = new Artist(); artist.save(); 

这给了我一个NullPointerException尝试访问Artist.save()中的artistDao。

任何想法我做错了什么?

马丁

您需要启用加载时织入(或其他types的织造)才能使用@Configurable 。 确保按照7.8.4加载时间在Spring框架中使用AspectJ进行编织所描述的那样正确启用了它。

我遇到了Tomcat 7使用LTW尝试将bean自动装入我的域类的问题。

http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-configurable-container上发现了3.2.x的文档更新,可以使用@EnableSpringConfigured而不是xmlconfiguration。;

所以我在我的Domain对象上有下面的注解:

 @Configurable(preConstruction=true,dependencyCheck=true,autowire=Autowire.BY_TYPE) @EnableSpringConfigured 

@EnableSpringConfigured是一个替代

 <context:spring-configured /> 

不要忘记添加到您的上下文XML文件:

 <context:load-time-weaver weaver-class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver" aspectj-weaving="on"/> 

当然,我需要先设置Tomcat进行加载时间编织。

另外,我遇​​到了一个3.2.0(空指针)的bug,所以我需要升级到Spring 3.2.1( https://jira.springsource.org/browse/SPR-10108

一切都很好!

首先,启用Springdebugging日志logging。 我使用Log4j来做到这一点。 我已经创build了一个logging器(使用Log4j xmlconfiguration,因此我可以使用RollingFileAppender):

 <log4j:configuration> <appender name="roll" class="org.apache.log4j.rolling.RollingFileAppender"> blah blah configuration blah blah </appender> <logger name="org.springframework"> <level value="debug" /> <appender-ref ref="roll" /> </logger> </log4j:configuration> 

这将让你看到spring在做什么,什么时候在做什么。

其次,你有ArtistDAO autowired,但是我没有看到你有一个名为ArtistDAO的bean。 您的DAO组件bean默认命名为“artistDaoImpl”。 尝试将@Component更改为@Component("artistDao") ,并将@Autowired应用于setter:

 private ArtistDAO artistDao; @Autowired public void setArtistDao(ArtistDAO artistDao) { this.artistDao = artistDao; } 

你应该看看Spring Roo是如何做的,因为它确实是你想做的事情。

有很多事情可以导致NPE你有,但是大部分时间与AspectJ编译器没有正确编译,而没有AspectJ libpath中的Spring Aspects jar (这与你的类path不同)有关。

首先尝试使用Maven和AspectJ编译器插件。 这就是为什么我build议springRoo,因为它会产生一个正确的设置POM文件。

我发现@Configurable实际上并不适用于LTW(尽pipe其中一个答案是这样的)。 您需要编译时编织@Configurable才能工作,因为build议是在对象构build时发生的(构造函数的build议不能用Spring LTW完成)。

我有同样的问题,并没有设法使@Configurable和@Autowired的代码工作。 我终于决定自己编写一个方面来处理@Configurable和@Autowired注解。 这里是代码:

 import java.lang.annotation.Annotation; import java.lang.reflect.Field; import org.apache.log4j.Logger; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @SuppressWarnings( "rawtypes" ) @Aspect public class AutoInjectDependecyAspect implements ApplicationContextAware { private static final Logger LOGGER = Logger.getLogger( AutoInjectDependecyAspect.class ); private ApplicationContext applicationContext = null; @Pointcut( "execution( (@org.springframework.beans.factory.annotation.Configurable *).new())" ) public void constructor() { } @Before( "constructor()" ) public void injectAutoWiredFields( JoinPoint aPoint ) { Class theClass = aPoint.getTarget().getClass(); try{ Field[] theFields = theClass.getDeclaredFields(); for ( Field thefield : theFields ) { for ( Annotation theAnnotation : thefield.getAnnotations() ) { if ( theAnnotation instanceof Autowired ) { // found a field annotated with 'AutoWired' if ( !thefield.isAccessible() ) { thefield.setAccessible( true ); } Object theBean = applicationContext.getBean( thefield.getType() ); if ( theBean != null ) { thefield.set( aPoint.getTarget(), theBean ); } } } } } catch ( Exception e ) { LOGGER.error( "An error occured while trying to inject bean on mapper '" + aPoint.getTarget().getClass() + "'", e ); } } @Override public void setApplicationContext( ApplicationContext aApplicationContext ) throws BeansException { applicationContext = aApplicationContext; } } 

接下来在你的spring上下文中定义方面,这样springcontext就会被注入到方面

 <bean class="[package_name].AutoInjectDependecyAspect" factory-method="aspectOf"/> 

也许使用DAO @Repository注解将做到这一点。

尝试:@Configurable(autowire = Autowire.BY_TYPE)。 自动assembly默认为closures:<

我有一个类似的问题,我今天解决。 重要的是你需要启用加载时织入,并确保加载适当的aspectj类。 在您的pom.xml中,您需要添加aspectjweaver工件 :

 ... <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.12</version> </dependency> .... 

如果需要,可以更改版本。 然后,我会去你的application-context.xml而不是DTD路由的xsd路由:

 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!--Scans the classpath for annotated components @Component, @Repository, @Service, and @Controller --> <context:component-scan base-package="your.base.package"/> <!--Activates @Required, @Autowired, @PostConstruct, @PreDestroy and @Resource --> <context:annotation-config/> <!--This switches on the load-time weaving for @Configurable annotated classes --> <context:load-time-weaver/> </beans> 

另外,请确认您的AspectJ版本是最新版本。 我花了几个小时试图做这个工作,原因是一个老版本的Aspectjweaver.jar。 我更新到1.7.2,一切都像一个魅力。

有@Configurable和LTW的错误。 如果您在任何方法中将您的class级用作参数,则自动布线停止工作。 https://jira.spring.io/plugins/servlet/mobile#issue/SPR-8502