I am trying to do a full annotations (no xml) implementation of Spring. The autowired members are not being populated. From my research, there are 3 things to do:
Set up a config file that manages the bean
Use @Autowired
to get the bean to the file
Instantiate an application context to get the ball rolling
It is difficult to find a complete example of this which uses annotations only, so I don't have much to reference. Most examples use at least some xml.
There is no error message, so I don't have any idea where the problem is. The value is just null. Here are my files:
Trivial.java
public class Trivial {
public TrivialBean trivialBean;
@Autowired
public void setTrivialBean(TrivialBean trivialBean) {
this.trivialBean = trivialBean;
}
public static void main(String...args) {
ApplicationContext context
= new AnnotationConfigApplicationContext(
TrivialConfig.class);
new Trivial().go();
}
private void go() {
System.out.println("trivialBean: " + trivialBean);
}
}
TrivialBean.java
public class TrivialBean {
public String foo = "TEST TEST TEST";
@Override
public String toString() {
return foo;
}
}
TrivialConfig.java
@Configuration
public class TrivialConfig {
@Bean
public TrivialBean trivialBean() {
return new TrivialBean();
}
}
I would expect this to output trivialBean: TEST TEST TEST
, but is just outputs trivialBean: null
In order for autowiring to work, the lifecycle of the instance of Trivial
has to be managed by the Spring container.
Example
TrivialBean.java is the same
public class TrivialBean {
public String foo = "TEST TEST TEST";
@Override
public String toString() {
return foo;
}
}
TrivialConfig.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class TrivialConfig {
@Bean
public TrivialBean trivialBean() {
return new TrivialBean();
}
@Bean
public Trivial trivial() {
return new Trivial();
}
}
Trivial.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Trivial {
public TrivialBean trivialBean;
@Autowired
public void setTrivialBean(TrivialBean trivialBean) {
this.trivialBean = trivialBean;
}
public static void main(String... args) {
ApplicationContext context = new AnnotationConfigApplicationContext(TrivialConfig.class);
Trivial trivial = context.getBean(Trivial.class);
trivial.go();
}
private void go() {
System.out.println("trivialBean: " + trivialBean);
}
}
Output
trivialBean: TEST TEST TEST
Please consult Spring documentation for more information on Annotation-based container configuration.
It is possible to autowire TrivialBean
instance into Trivial
instance created by new
.
spring-aspects.jar
contains an annotation-driven aspect that allows dependency injection for objects created outside of the control of the container. However, it should not be used in new Spring-based projects. It is intended to be used for legacy projects, where for some reason some instances are created outside of the Spring container.
Example for Spring 4.2.0 (the latest at the moment), AspectJ 1.8.6 (the latest at the moment), Maven and Java 1.8.
Additional dependencies on spring-aspects
and aspectjrt
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.6</version>
</dependency>
Compile time weaving via AspectJ Maven
plugin
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<encoding>UTF-8</encoding>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
<Xlint>warning</Xlint>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
TrivialBean.java is the same
public class TrivialBean {
public String foo = "TEST TEST TEST";
@Override
public String toString() {
return foo;
}
}
TrivialConfig.java
@EnableSpringConfigured
is analogous to <context:spring-configured>
. It signals the current application context to apply dependency injection to classes that are instantiated outside of the Spring bean factory.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.aspectj.EnableSpringConfigured;
@Configuration
@EnableSpringConfigured
public class TrivialConfig {
@Bean
public TrivialBean trivialBean() {
return new TrivialBean();
}
}
Trivial.java
@Configurable
applies Spring-driven configuration to Trivial
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@Configurable
public class Trivial {
public TrivialBean trivialBean;
@Autowired
public void setTrivialBean(TrivialBean trivialBean) {
this.trivialBean = trivialBean;
}
public static void main(String... args) {
ApplicationContext context = new AnnotationConfigApplicationContext(TrivialConfig.class);
Trivial trivial = new Trivial();
trivial.go();
}
private void go() {
System.out.println("trivialBean: " + trivialBean);
}
}
Output
trivialBean: TEST TEST TEST
It works! Please consult Spring documentation for more information on AspectJ and @Configurable.