I have the following spring configuration:
Use compile time weaving, see for plugin example at: https://github.com/avner-levy/minimal_spring_hibernate_maven_setup/blob/master/pom.xml
The following combination of annotation and Spring config works for me thanks to notes above by Tobias/Willie/Eric:
Class:
package com.abc
@Configurable
@Aspect
public class MyAspect {
@Autowired
protected SomeType someAutoWiredField;
}
XML:
<context:spring-configured />
<context:component-scan base-package="com.abc" />
The aspect is a singleton object and is created outside the Spring container. A solution with XML configuration is to use Spring's factory method to retrieve the aspect.
<bean id="syncLoggingAspect" class="uk.co.demo.SyncLoggingAspect"
factory-method="aspectOf" />
With this configuration the aspect will be treated as any other Spring bean and the autowiring will work as normal.
You have to use the factory-method also on Enum objects and other objects without a constructor or objects that are created outside the Spring container.
This blog post explains it really well. Due to the fact that aspect singleton is created outside spring container you'd need to use factory-method=”aspectOf” that is only available after it is woven in by AspectJ ( not Spring AOP ) :
Notice factory-method=”aspectOf” that tells Spring to use a real AspectJ ( not Spring AOP ) aspect to create this bean. So that after the aspect is woven in it has an “aspectOf” method.
So that :
No matching factory method found: factory method 'aspectOf()' - That would mean that the aspect was not woven by AspectJ weaver.
From my experience with spring 3.1, if I don't use @Autowired but traditional setter for dependency injection, it gets injected and works as expected without aspectJ weaver. Although I'm encountering problems with the aspect being singleton... It results in 'perthis' instantiation model. .
Another option is to add @Configurable
to your aspect class instead of messing around with XML.
Configuring @Autowired with java config only (so no XML based configuration) requires a bit of extra work than just adding @Configuration to the class, as it also needs the aspectOf method.
What worked for me was creating a new class:
@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;
}
}
And then use that in you aspect in conjunction with using @DependsOn @Configured and @Autowired:
@DependsOn("springApplicationContextHolder")
@Configuration
@Aspect
public class SomeAspect {
@Autowired
private SomeBean someBean;
public static SomeAspect aspectOf() {
return SpringApplicationContextHolder.getApplicationContext().getBean(SomeAspect.class);
}
The @DependsOn is needed because spring can't determine the dependency because the bean is used staticly.
Add @Component to aspect class and your dependencies should get injected automatically. and add context:component-scan for package where your aspect is in spring context file.
@Component
@Aspect
public class SomeAspect {
/* following dependency should get injected */
@Autowired
SomeTask someTask;
/* rest of code */
}