我正在尝试使用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>
类路径扫描和初始化由弹簧模块执行Play!框架,虽然其他autowired bean工作,所以我很确定这不是根本原因。我正在使用Spring 3.0.5。
在其他代码中(实际上在使用Spring注入我的控制器的bean中的方法内),我这样做:
Artist artist = new Artist();
artist.save();
这给了我一个NullPointerException试图访问Artist.save()中的artistDao。
知道我做错了吗?
马丁
答案 0 :(得分:9)
您需要启用加载时编织(或其他类型的编织)才能使用@Configurable
。确保正确启用它,如7.8.4 Load-time weaving with AspectJ in the Spring Framework。
答案 1 :(得分:6)
我在使用LTW尝试将bean自动装入我的域类时遇到了Tomcat 7的这个问题。
在http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-configurable-container的3.2.x文档中有一些更新,显示可以使用@EnableSpringConfigured而不是xml配置。
所以我在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中的错误(空指针)所以我需要升级到Spring 3.2.1(https://jira.springsource.org/browse/SPR-10108)
一切都很好!
答案 2 :(得分:4)
首先,启用Spring调试日志记录。我使用Log4j来做到这一点。我已经创建了一个这样的记录器(使用Log4j xml配置,所以我可以使用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,但我看不到您在哪里有一个名为ArtistDAO的bean。默认情况下,您的DAO组件bean将命名为“artistDaoImpl”。尝试将@Component
更改为@Component("artistDao")
并将@Autowired
应用于设置者:
private ArtistDAO artistDao;
@Autowired
public void setArtistDao(ArtistDAO artistDao)
{
this.artistDao = artistDao;
}
答案 3 :(得分:4)
您应该看看Spring Roo是如何做到的,因为它完全符合您的要求。
有很多东西可以导致您拥有NPE,但大部分时间都与未使用 AspectJ编译器正确编译而没有 Spring Aspects jar 您的AspectJ lib路径中的strong>(这与您的类路径不同)。
首先尝试使用Maven和AspectJ编译器插件。这就是为什么我推荐Spring Roo,因为它会生成一个具有正确设置的POM文件。
我发现@Configurable并不适用于LTW(尽管其中一个答案是这样说的)。您需要编译时编织@Configurable才能工作,因为建议发生在对象构造时(使用Springs LTW无法完成构造函数建议)。
答案 4 :(得分:3)
我遇到了同样的问题,但从未设法让代码与@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"/>
答案 5 :(得分:1)
也许使用DAO的@Repository注释就可以了。
答案 6 :(得分:1)
尝试:@Configurable(autowire = Autowire.BY_TYPE)。自动装配默认为关闭:&lt;
答案 7 :(得分:1)
我有一个类似的问题,我今天解决了。重要的是您需要启用加载时编织并确保加载适当的aspectj类。在您的pom.xml中,您需要添加aspectjweaver artifact:
...
<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>
答案 8 :(得分:0)
另外,请确认您的AspectJ版本是最新版本。我浪费了几个小时试图完成这项工作,原因是Aspectjweaver.jar的旧版本。我更新到1.7.2,一切都像魅力一样。
答案 9 :(得分:0)
@Configurable和LTW存在错误。如果在任何方法中将类用作参数,则自动接线将停止工作。 https://jira.spring.io/plugins/servlet/mobile#issue/SPR-8502