I define a bean in a configuration class. I would like to autowire this bean in a component. However, the property stays null. E.g.:
Appconfiguration.java
#Configuration
public class AppConfiguration {
#Bean
public SomeType someObject() {
return new SomeType();
}
}
AppComponent.java
#Component
public class AppComponent {
#Autowired
private SomeType someObject; // TODO why null?
public AppComponent() { // note: passing a SomeType constructor argument works
System.out.println(someObject);
}
}
How can I autowire a bean defined in a configuration class?
Are you missing a fundamental detail that properties are injected after a bean is created? Have you tried access your property after a bean is fully initialized?
Update:
I've reworked your example a little to demonstrate you the difference:
#Test
public void initializationTest() {
try (AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext()) {
context.register(AppConfiguration.class, AppComponent.class);
context.refresh();
}
}
#Configuration
public class AppConfiguration {
#Bean
public SomeType someObject() {
return new SomeType();
}
}
#Component
public class AppComponent {
#Autowired
private SomeType someObject;
public AppComponent() {
// Here properties are not yet injected by Spring IoC container
System.out.println(someObject); // Obviously prints null
}
/**
* Method is invoked after a bean is initialized and all its properties are being set.
*/
#PostConstruct
private void init() {
System.out.println(someObject); // Prints SomeType#6b419da
}
}
public class SomeType {
}
So basically bean lifecycle consists of the following steps:
1. Bean instance is created
2. Bean properties are set
3. In case bean implements Aware interfaces - those implemented methods are invoked
4. BeanPostProcessor#postProcessBeforeInitialization methods of custom bean post-processors are invoked
5. Initialization callbacks are invoked in the following order:
5.1. #PostConstruct method is invoked
5.2. InitializingBean#afterPropertiesSet() method is invoked
5.3. #Bean#initMethod() method is invoked
Bean is fully initialized now.
6. BeanPostProcessor#postProcessAfterInitialization methods of custom post-processors are invoked
are invoked.
7. Destruction callbacks are invoked in the following order:
7.1. #PreDestroy method is invoked
7.2. DisposableBean#destroy() method is invoked
7.3. #Bean#destroyMethod method is invoked
Related
As far as I understood, Spring manages autowiring mechanism with AutowiredAnnotationBeanPostProcessor on postProcessBeforeInitialization stage. But how does it inject proxies that ought to be created on postProcessAfterInitialization stage?
EDIT 1
Suppose I have this Spring configuration
#Service
class RegularBean {
// injected on postProcessBeforeInitialization stage
#Autowired
private TransactionBean tBean;
// invoked in between of postProcessBeforeInitialization and postProcessAfterInitialization
#PostConstruct
void init() {
tBean.transactionMethod();
}
}
#Service
class TransactionBean {
// transactional proxy is created on postProcessAfterInitialization stage
#Transactional
public void transactionMethod() { ... }
}
Transactional proxy is created on postProcessAfterInitialization stage. But #PostConstruct is called right before it. Is injected tBean wrapped with transactional proxy? If it so, then why? Because it should not be. If it is not wrapped, then how transactions are going to be handled in the future?
Suppose that I replace field-injection with constructor-injection. Will it change the behavior somehow?
When you use autowiring on method or field ,Spring Container not always create and inject the required field/attribute instance. Spring internally create smart proxies and inject the proxies to your bean. This smart proxy will resolve the bean at later point and delegate call to actual bean during method invocation. This is a common strategy we use to resolve request and session scoped beans to singleton instance (Say service layer beans) using Scope annotation.
Adding small snippet to show Spring internally create proxies for Object. Consider a classic circular dependency case when we use Constructor injection.
#Component
public class CircularDependencyA {
private CircularDependencyB circB;
public CircularDependencyA(#Lazy CircularDependencyB circB) {
System.out.println("CircularDependencyA Ctr ->"+circB.getClass().getName());
this.circB = circB;
}
}
#Component
public class CircularDependencyB {
private CircularDependencyA circA;
public CircularDependencyB(CircularDependencyA circA) {
System.out.println("CircularDependencyB Ctr ->"+circA.getClass().getName());
this.circA = circA;
}
}
#Configuration
#ComponentScan(basePackages = { "com.example.springdemo.cd" })
public class TestConfig {
}
public class TestCircularDependency {
public static void main(String[] args) {
try(AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(TestConfig.class);){
}
}
}
Based on our hints Spring is creating Proxy(using CGLIB) for CircularDependencyB Object and see the op from the CircularDependencyA Constructor
CircularDependencyA Ctr ->com.example.springdemo.cd.CircularDependencyB$$EnhancerBySpringCGLIB$$e6be3b79
Thanks
This website says beans registered inside component classes are not cglib proxied and do not go through the spring container. So does this mean if I register a bean inside a component class (snippet below), adding #Scope("request") wont make any difference, and a new instance of AnotherBean will always be created whenever testBean.anotherBean() is called from some external class?
#Component
public class TestBean {
#Bean
#Scope("request")
public AnotherBean anotherBean() {
return new AnotherBean();
}
}
The bean that is not cglib proxied is the #Component itself, not the bean registered using the #Bean annotation. If you are not calling the anotherBean method explicitly, it won't make a difference because the proxy is used to return the bean when the method annotated with #Bean is called. See the example
The bean testBeanComponent is not cglib proxied :
#Component
public class TestBeanComponent {
#Bean
#Scope("request")
public AnotherBeanComponent anotherBeanComponent() {
return new AnotherBeanComponent();
}
}
The bean testBeanConfiguration is cglib proxied :
#Configuration
public class TestBeanConfiguration {
#Bean
#Scope("request")
public AnotherBeanConfiguration anotherBeanConfiguration() {
return new AnotherBeanConfiguration();
}
}
What it mean :
#Service
public class TestService {
#Autowired //Inject a normal bean
private TestBeanComponent testBeanComponent;
#Autowired //Inject a proxy
private TestBeanConfiguration testBeanConfiguration;
public void test() {
//Calling anotherBeanComponent always return a new instance of AnotherBeanComponent
testBeanComponent.anotherBeanComponent()
.equals(testBeanComponent.anotherBeanComponent()); // is false
//Calling anotherBeanConfiguration return the bean managed by the container
testBeanConfiguration.anotherBeanConfiguration()
.equals(testBeanConfiguration.anotherBeanConfiguration()); // is true
}
}
But if you are injecting the bean instead of using the method, everything will work as you expected :
#Service
public class TestService2 {
#Autowired //Inject a proxy with scope request
private AnotherBeanComponent anotherBeanComponent;
#Autowired //Inject a proxy with scope request
private AnotherBeanConfiguration anotherBeanConfiguration;
}
I'm developing a Spring Boot application and am trying out using Java annotation-based bean creation (using #Configuration and #Bean) rather than the familiar old XML-based bean creation. I'm puzzled though. If I attempt to create a bean in XML but fail to set an #Required property I get a BeanInitializationException when the application context is created. In my trials so far with annotation-based bean creation though this does not seem to be the case.
For example:
public class MyClass {
...
#Required
public void setSomeProp(String val){
}
}
Then in Spring XML:
<bean class="MyClass"/>
This will blow up during application startup (and IntelliJ flags it) because the required property is not set. But the same does not seem to be true of this:
#Configuration
public class MyConfig {
#Bean
public MyClass myClass() {
return new MyClass();
}
}
This application starts up just fine even though the required property is not ever set. I must be missing something here, because this seems like a pretty key feature in Spring.
UPDATE
I did some digging & debugging and it turns out that the bean definition is somehow being flagged to skip checking that #Required fields are set. In the Spring class 'RequiredAnnotationBeanPostProcessor' the boolean method 'shouldSkip()' is returning true for beans created this way. When I used the debugger to force that method to return false bean creation did indeed blow up with the expected exception.
Seeing as I'm making a pretty basic Spring Boot application I'm inclined (as Zergleb suggests) to submit this as a bug.
UPDATE 2
Some further debugging has revealed that even if the field is getting set forcing the check still throws the same exception, as if it hadn't been set. So perhaps dunni is correct and there is no way for this to work with #Bean notation.
As you said I also could not get #Required to run as expected this may be a bug and needs to be reported. I have a few other suggestions that did work for me.
Class annotated with #Configuration
//With the bean set up as usual These all worked
#Bean
public MyClass myClass() {
return new MyClass();
}
When you annotate the class #Component and load using component scanning works as expected.(The component scanning part is important you either need your #Configuration class to either have #ComponentScan or perhaps remove #Configuration and replace with #SpringBootApplication and this will enable scanning for components without needing to wire them up using #Bean configs)
#Component // Added this
public class MyClass {
...
#Required //Failed as expected
public void setSomeProp(String val){
}
}
Use #Autowired(required=true) //Fails with BeanCreationException //No qualifying bean of type [java.lang.String] found for dependency
//No more #Component
public class MyClass {
...
#Autowired(required=true) //Fails
public void setSomeProp(String val){
}
}
#Autowired required=false //Does not crash
public class MyClass {
...
#Autowired(required=false) //Simply never gets called if missing
public void setSomeProp(String val){
}
}
#Value //Does not work if test.property is missing // Could not resolve placeholder 'test.property' in string value "${test.property}
public class MyClass {
#Value("${test.property}")
String someProp;
//This getter is not neccesary neither is a setter
public String getSomeProp() {
return this.someProp;
}
}
#Value with default value//Does not crash // When getSomeProp is called it returns "My Default Value"(Unless you have test.property=Anything in your application.properties file then it returns "Anything"
public class MyClass {
#Value("${test.property:My Default Value}")
String someProp;
//This getter is not neccesary neither is a setter
public String getSomeProp() {
return this.someProp; //Returns "My Default Value"
}
}
Inside your #Configuration file also fails if it cannot find anything to populate String someProp in the myClass method
#Bean
public MyClass myClass(String someProp) { //Fails being unable to populate this arg
MyClass myObj = new MyClass();
myObj.setSomeProp(someProp);
return ;
}
If course this won't work, since you create the object of MyClass yourself (new MyClass()), thus the annotations are not evaluated. If you create a bean with a #Bean method, the container will only make sure, that all dependencies are there (method parameters) and that the bean scope is adhered to, meaning if it's a singleton bean, only one bean is created per application context. The creation of the bean/object itself is solely the responsibility of the developer.
The equivalent of the xml <bean> tag is annotating the class with #Component, where the bean is created completely by the container, thus the annotations are evaluated.
As it is being said that when you are having your own #Configuration class where you are creating the bean by itself, #Required doesn't apply there.
When you already have a #Component, let Spring Boot do the component scan and at the required setter property you can add #Autowired and it will work fine.
Found this link on web- https://www.boraji.com/spring-required-annotation-example
For example:
I have a Component called Employee having Id and Name.
#Component
public class Employee {
int id;
String name;
public int getId() {
return id;
}
#Autowired
#Required
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I have a Configuration class called AppConfig.java
#Configuration
public class AppConfig {
#Bean
public int getId() {
return 1;
}
}
So now we see, that component Employee needs an Id property for binding during startup, so I wrote bean method of type Integer, which will get autowired during runtime. If you do not write a bean of type Integer, it will result a BeanCreationException.
And here is my main class file.
#SpringBootApplication
public class SingletonApplication {
public static void main(String[] args) {
ApplicationContext ctx =
SpringApplication.run(SingletonApplication.class, args);
Employee emp = (Employee)ctx.getBean(Employee.class);
System.out.println(emp.getId());
}
}
In Spring XML, I can define a bean that instantiates a class annotated with #Configuration. When I do, that bean is post-processed. Any methods inside that class with #Bean are also added to the container. How do I perform a similar post-processing in JavaConfig?
Here's the XML version:
<bean id="test" class="com.so.Test">
<property name="prop" value="set before instantiating #Beans defined in Test"/>
</bean>
The associated Test class:
#Configuration
class Test {
private String prop;
void setProp(final String prop) {
this.prop = prop;
}
#Bean
NeedThisBean needThisBeanToo() {
return new NeedThisBean(prop);
}
}
If I use Spring XML Config, both test and needThisBeanToo are available in the container. needThisBeanToo is added via a BeanPostProcessor, though I can't recall which one. If I use JavaConfig, only test is available in the container. How do I make needThisBeanToo available to the container? #Import would work, except that prop being set is required for needThisBeanToo to be initialized correctly.
The part that makes all of this complicated is that Test is vended from a library I'm consuming. I don't control Test, nor can I change it. If I drive it from JavaConfig, it would look like this:
#Configuration
class MyConfiguration
{
#Bean
Test test() {
Test test = new Test();
test.setProp("needed to init `needThisBeanToo` and others");
return test;
}
}
The JavaConfig example does not instantiate needThisBeanToo despite it being defined in Test. I need to get needThisBeanToo defined, preferably without doing it myself, since I don't want to copy code I don't own. Delegation isn't attractive, since there are a number of subsequent annotations/scopes defined on needThisBeanToo (and others defined inside Test).
Your problem is is that you're ignoring the #Configuration annotation completely. Why is that?
When code reaches this line Test test = new Test(); it just doesn't do anything with #Configuration. Why? Because annotation is not something that a constructor is aware of. Annotation only marks some meta-data for the class. When spring loads classes it searches for annotations, when you call a constructor of a class, you don't. So the #Configuration is just ignored because you instantiate Test with new Test() and not through spring.
What you need to do is to import Test as a spring bean. Either via XML as you showed in your question OR using #Import. You problem with prop is that the setter isn't called because that's just not the way to do it. What you need to be doing is either do something like that:
#Configuration
class Test {
private String prop = "set before instantiating #Beans defined in Test";
#Bean
NeedThisBean needThisBeanToo() {
return new NeedThisBean(prop);
}
}
Or to create a property in spring (this is a different subject) and inject the value:
#Configuration
class Test {
#Autowired
#Value("${some.property.to.inject}") // You can also use SPeL syntax with #{... expression ...}
private String prop;
#Bean
NeedThisBean needThisBeanToo() {
return new NeedThisBean(prop);
}
}
You can also create a bean of type String and inject it as follows:
#Configuration
class Test {
#Autowired
#Qualifer("nameOfBeanToInject")
private String prop;
#Bean
NeedThisBean needThisBeanToo() {
return new NeedThisBean(prop);
}
}
In the last case you can define your original MyConfiguration with this bean:
#Configuration
#Import(Test.class)
class MyConfiguration
{
#Bean(name = "nameOfBeanToInject")
String test() {
return "needed to init `needThisBeanToo` and others";
}
}
In any case you have to import Test either using #Import or as a normal XML bean. It won't work by calling the constructor explicitly.
Here's a way to handle vended #Configuration classes that require some properties to be set prior to creating their #Beans:
Vended #Configuration class:
#Configuration
class Test {
private String property;
public setProperty(final String property) {
this.property = property;
}
#Bean
PropertyUser propertyUser() {
return new PropertyUser(property);
}
#Bean
SomeBean someBean() {
// other instantiation logic
return new SomeBeanImpl();
}
}
Here's the consuming #Configuration class:
#Configuration
class MyConfig {
#Bean
static String myProperty() {
// Create myProperty
}
/**
* Extending Test allows Spring JavaConfig to create
* the beans provided by Test. Declaring
* Test as a #Bean does not provide the #Beans defined
* within it.
*/
#Configuration
static class ModifiedTest extends Test {
ModifiedTest() {
this.setProperty(myProperty());
}
#Override
#Bean
SomeBean someBean() {
return new SomeBeanCustomImpl(this.propertyUser());
}
}
Can anyone explain me why a #Bean on a static method is returning 2 different instances ?
I can understand that #Bean on a method non static like the class A is returning the same instance because default scope is singleton.
And If I try to inject the class B with #Autowire in a Service it won't work, so it looks like it's not load by the Spring App Context. So using a class like D will be similar !?
I think not because for #PropertySource we need to use in addition (used for the placeholder):
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
and if we remove #Bean from this, it won't work.
Is there other use case where it would be useful to use #Bean on a static method?
EXAMPLE:
when I run:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {Conf.class})
public class Test {
#org.junit.Test
public void test(){
}
}
for
#Configuration
#ComponentScan
public class Conf {
#Bean
public A aaa(){
return new A();
}
#Bean
public static B bbb(){
return new B();
}
#Bean
#Scope("prototype")
public C ccc(){
return new C();
}
public static D ddd(){
return new D();
}
#PostConstruct
public void post(){
System.out.println(aaa());
System.out.println(aaa());
System.out.println(bbb());
System.out.println(bbb());
System.out.println(ccc());
System.out.println(ccc());
System.out.println(ddd());
System.out.println(ddd());
}
}
public class A {
}
public class B {
}
public class C {
}
public class D {
}
I get:
uk.co.xxx.unit.A#6caf0677
uk.co.xxx.unit.A#6caf0677
uk.co.xxx.unit.B#413d1baf
uk.co.xxx.unit.B#16eb3ea3
uk.co.xxx.unit.C#353352b6
uk.co.xxx.unit.C#4681c175
uk.co.xxx.unit.D#57a78e3
uk.co.xxx.unit.D#402c4085
Because you create a new object for every method call to bbb(). Inter-bean dependencies (if you just call the bean producing method) work in that way, that a proxy is created for your configuration class, and the proxy intercepts method calls to the bean methods to deliver the correct bean (singleton, prototype etc.). However, static methods are not proxied, so when you call the static method, Spring doesn't know about it and you just get the regular Java object. With the PropertySourcesPlaceholderConfigurer it is different, because that method isn't directly called in that class, the bean will only be injected where it is used.
#Bean annotated methods get proxied in order to provide the correct bean instance. Static methods do not get proxied. Hence in your case bbb() invocation each time gives a new instance of B.
PropertySourcesPlaceholderConfigurer class is a special kind of bean since it implements BeanFactoryPostProcessor. In the container lifecycle, a BeanFactoryPostProcessor object must be instantiated earlier than an object of #Configuration-annotated class. Also you don't need to call this static method.
See Bootstrapping section in the java doc : [http://docs.spring.io/spring/docs/4.2.x/javadoc-api/org/springframework/context/annotation/Bean.html][1]
Special consideration must be taken for #Bean methods that return
Spring BeanFactoryPostProcessor (BFPP) types. Because BFPP objects
must be instantiated very early in the container lifecycle, they can
interfere with processing of annotations such as #Autowired, #Value,
and #PostConstruct within #Configuration classes. To avoid these
lifecycle issues, mark BFPP-returning #Bean methods as static