摘要:
我在@PostConstruct
@Service
ServiceInitialiserFacsimile
执行了一些初始化操作。这些操作包括在执行方法(DoAttionalStuffAspect
)之后调用方法。
Aspect通过aspectOf即时显示,因此它由Spring容器处理,但不幸的是,它的依赖关系被注入 AFTER ServiceInitialiserFacsimile @PostConstruct
的执行,导致NullPointerException。
如何告诉Spring容器首先注入Aspect中的字段然后实例化ServiceInitialiserFacsimile
?
我尝试使用Autowired构造函数来表示方面,但我认为最终AspectJ需要no-arg构造函数,所以没有帮助
CODE
这是我为了重现我在一个更复杂的应用程序中遇到的问题而创建的示例。如果您想查看它,这是项目。 https://github.com/alessiop86/spring3-mvc-maven-xml-hello-world
以下代码: 这是初始化类:
@Component
public class ServiceInitialiserFacsimile {
private final SampleService sampleService;
@Autowired
public ServiceInitialiserFacsimile(SampleService ss) {
this.sampleService = ss;
}
@PostConstruct
public void initialiseAllTheServices() {
this.sampleService.init();
}
}
这是具有某些自定义逻辑的服务,需要由ServiceInitialiserFacsimile
@PostConstruct
进行初始化:
@Service
public class SampleService {
public void init() {
System.out.println("do some stuff");
try {
execute();
}
catch(Exception e) {
System.err.println("I do not want to block to whole framework initialisation");
}
}
@DoAdditionalStuff
public void execute() {
System.out.println("Phase 1");
}
}
这是我在方面定义中使用的注释
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DoAdditionalStuff {
}
这是方面
@Aspect
public class AdditionalStuffAspect {
private AdditionalStuffService service;
public AdditionalStuffService getService() {
return service;
}
public void setService(AdditionalStuffService service) {
this.service = service;
}
@Pointcut(value="execution(public * *(..))")
private void anyPublicMethod() { }
@AfterReturning("anyPublicMethod() && @annotation(doAdditionalStuff)")
public void afterReturning(JoinPoint jointPoint, DoAdditionalStuff doAdditionalStuff) {
System.out.println(jointPoint);
service.doStuff();
}
}
这是创建的服务,但在运行方面时尚未实例化:
@Service
public class AdditionalStuffService {
public void doStuff() {
System.out.println("Phase2: additional stuff");
}
}
Spring context xml配置文件:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:component-scan base-package="initialisation.mess"/>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<mvc:resources mapping="/resources/**" location="/resources/"/>
<mvc:annotation-driven/>
<bean class="initialisation.mess.aspects.AdditionalStuffAspect" factory-method="aspectOf">
<property name="service" ref="additionalStuffService" />
</bean>
</beans>
答案 0 :(得分:0)
通过在xml中设置id,我能够从Aspect强制执行对ServiceInitialiserFacsimile的依赖:
<bean id="myAspect" class="initialisation.mess.aspects.AdditionalStuffAspect" factory-method="aspectOf">
<property name="service" ref="additionalStuffService" />
</bean>
然后使用ServiceInitialiserFacsimile
注释指定弹簧托管AdditionalStuffAspect
中@DependsOn
的依赖关系:
@Component
@DependsOn("myAspect")
public class ServiceInitialiserFacsimile {
private final SampleService sampleService;
@Autowired
public ServiceInitialiserFacsimile(SampleService ss) {
this.sampleService = ss;
}
@PostConstruct
public void initialiseAllTheServices() {
this.sampleService.init();
}
}