Spring boot Autowired not working in Configuration class
@Import is to add a configuration class into another configuration class.
http://docs.spring.io/spring-javaconfig/docs/1.0.0.M4/reference/html/ch04s03.html
@ComponentScan is to scan for components declared in your code, like @Service, @Component, @Repository, among others.
http://docs.spring.io/spring-javaconfig/docs/1.0.0.M4/reference/html/ch06s02.html
I think you need to add in your configuration class the @ComponentScan so it can scan the package with your component classes.
@Configuration
@ComponentScan(value = "org.foo.path.baseFolder")
public class MyConfiguration {
@Autowired
protected GlobalPropertiesLoader globalPropertiesLoader;
Why when use @Autowired in @Configuration in Spring failed sometimes?
Because the order to load EagleBeanCreator
and EagleServiceBuilder
is not definite. You can use @Order
or @ConditionalOnClass
to make sure EagleBeanCreator
initialize first.
Autowire a bean within Spring's Java configuration
If you need a reference to the DataSource
bean within the same @Configuration
file, just invoke the bean method.
@Bean
public OtherBean someOtherBean() {
return new OtherBean(dataSource());
}
or have it autowired into the @Bean
method
@Bean
public OtherBean someOtherBean(DataSource dataSource) {
return new OtherBean(dataSource);
}
The lifecycle of a @Configuration
class sometimes prevents autowiring like you are suggesting.
How to Autowire a Spring-annotated service class in a @Configuration class?
Your error is the following (you are returning a null value):
@Bean
public SessionService sessionService() {
return sessionService;
}
Solution
Since your
SessionServiceImpl
is annotated with@Service
, you can just remove the@Bean
method and let spring create it. Spring already makes it available for you.Or, If your
SessionServiceImpl
wasn't annotated with@Service
, you would need the following :
@Bean
public SessionService sessionService() {
return new SessionService();
}
If this doesn't work, it may just be that your SessionServiceImpl
is in a package not being scanned by spring (as suggested by @Miloš Milivojević)
You may add @ComponentScan
to your Configuration class
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
@ComponentScan("com.package.to.sessionServiceImpl-or-higher")
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
Why is an @Autowired field within a @Configuration class null?
why must it happen that
accountRepository
is created before it's used
by newTransferServiceImpl()
?
It doesn't. accountRepository
may be seen to be null
.
From the note in the documentation you linked (its more current version)
Make sure that the dependencies you inject that way are of the
simplest kind only.@Configuration
classes are processed quite early
during the initialization of the context and forcing a dependency to
be injected this way may lead to unexpected early initialization.
Whenever possible, resort to parameter-based injection as in the
example above.Also, be particularly careful with
BeanPostProcessor
and
BeanFactoryPostProcessor
definitions via@Bean
. Those should usually
be declared asstatic
@Bean
methods, not triggering the instantiation
of their containing configuration class. Otherwise,@Autowired
and
@Value
won’t work on the configuration class itself since it is being
created as a bean instance too early.
In summary, a Configuration
class will end up being just another bean in the application context. As such, it will be processed by all registered BeanPostProcessor
beans.
@Autowired
is processed by AutowiredAnnotationBeanPostProcessor
. Presumably, you're using AnnotationConfigApplicationContext
which registers one automatically.
In your example, which is incomplete since
...but determining exactly where the autowired bean definitions are
declared is still somewhat ambiguous
However, we can assume some other configuration provided a bean definition for a AccountRepository
bean. Once the application context instantiates the ServiceConfig
bean, it can then post process it and inject @Autowired
targets.
The only reason an @Autowired
target could be null
in a @Configuration
bean instance is that you tried to read it before an AutowiredAnnotationBeanPostProcessor
could process/inject it.
Consider a circular dependency. Take the @Configuration
class in your snippet with an additional @ComponentScan
of the following classes
@Component
class AccountRepository {
public AccountRepository(Foo foo) {}
}
@Component
class Foo {
public Foo(TransferService ts) {}
}
The @Configuration
bean get initialized. AutowiredAnnotationBeanPostProcessor
kicks off to process the accountRepository
field. It looks for an AccountRepository
bean and tries to initialize it. It needs a Foo
bean to instantiate it (for constructor injection). It looks for a Foo
bean and tries to initialize it. It needs a TransferService
bean to instantiate it (for constructor injection). It looks for a TransferService
bean and finds the @Bean
factory method. It invokes it. The accountRepository
hasn't been initialized yet, so remains null
. You can verify this by putting a breakpoint in the @Bean
method and browsing the stack trace.
Had you used a parameter injection as suggested in the quote above
Whenever possible, resort to parameter-based injection as in the example above.
Spring would've crashed and warned you
Caused by:
org.springframework.beans.factory.BeanCurrentlyInCreationException
:
Error creating bean with name'accountRepository'
: Requested bean is
currently in creation: Is there an unresolvable circular reference?
That's the workaround I ended up doing
I can't currently explain this.
Autowire bean from @Configuration
You need to inject the RestTemplate
, not the config class
@Autowired
private RestTemplate restTemplate;
instead of:
@Autowired
private RestClientConfig restTemplate;
EDIT
Here is one way to pass your arguments to your class:
//EXAMPLE @Value("${propFile.maxTotalConn}")
@Bean
public RestTemplate createRestTemplate(@Value("${propFile.maxTotalConn}") int maxTotalConn, @Value("${propFile.maxPerChannel}") int maxPerChannel, connTimoutint connTimout) {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(maxTotalConn);
connectionManager.setDefaultMaxPerRoute(maxPerChannel);
...
}
EXPLANATION
Create a properties file (*.properties)
and place in your src/main/resources
folder. Include your properties in it as the code above suggests. @Value
is a Spring
annotation that searches for the properties file on the classpath
and injects the values while creating your Spring bean.
Related Topics
Webdriver: Check If an Element Exists
Access to Private Inherited Fields via Reflection in Java
How to Combine Two Lists into a Map (Java)
Merge (Concat) Multiple JSONobjects in Java
How to Initialize an Arraylist with All Zeroes in Java
Read File from Resources Folder in Spring Boot
How to Put All Required Jar Files in a Library Folder Inside the Final Jar File with Maven
Consistency of Hashcode() on a Java String
Httpurlconnection Timeout Settings
Delete Item from Array and Shrink Array
Java: How to Set Precision for Double Value
Can One Do a for Each Loop in Java in Reverse Order
Serialization - Readobject Writeobject Overrides
How to Test to See If a Double Is Equal to Nan
How to Solve Circular Reference in JSON Serializer Caused by Hibernate Bidirectional Mapping