#Component
public class BeanA {
...
}
#Component
public class BeanB {
#Autowired
BeanA beanA;
public BeanB() {
// Use beanA
beanA.method();
}
}
Can we assume BeanA is created and initialized before BeanB constructor is called? (I know we can pass BeanA as constructor arg to BeanB, this is more of curiosity question to understand spring/java initialisation sequence)
Take a look at http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-autowired-annotation-qualifiers
Setting properties on bean would happen after it is constructed by means of a constructor or a factory method. By default, beans are autowired by name and values are set using setter methods. So in your case the field will be set after constructor.
This is because
#Autowired
BeanA beanA;
really means that you want to autowire the field of that class instance. beanA in your case is not really a constructor arg.
(Well, here is a quick question, are the constructor argument names retained after compilation? Is there any debug flag related to this?)
As this example from spring documentation says, you can apply #Autowired to constructors and fields:
public class MovieRecommender {
#Autowired
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
#Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
Let me know if you need any more help with this.
Oh, and just a minor point. You seem to be calling method() on beanA in your constructor. It is not a good idea, if the method can be overridden. I know it is just an example you jotted down here, but just a word of caution.
No, the autowiring is handled by a BeanPostProcessor that will run after the constructor of the newly created bean. If, for some reason, you need to autowire some fields and then run some initialisation you can use a #PostConstruct annotated method. It will be called after all dependencies are injected. In most cases #Autowiring a constructor (and, perhaps, making the object immutable) is still the best option.
No, spring is very clever, but not that magical ... Internally, spring :
creates an instance
set instances properties
stores eventually the bean in relevant scope (exept for prototype beans) and/or gives it to caller
But the creation uses a constructor and at the time it is called properties have not been set.
In short, you can access #Autowired in your method marked with #PostConstruct.
Related
I have a Controller class that maps request urls. I have an instance of class annotated with #Service. For example;
#Controller
class MainController{
#Autowired
private UserService userService;
...
}
As I know, this instance is created automatically by Spring container, because I added #Autowired but I use this instance when condition is met in the method. If the condition is not met, I do not need this instance. Thus, this declaration is overhead. I mean, I may not use it even though it is created.
I would like to create the object when it is needed. How can I do this in the code? I probably will not use #Autowired because I need a dynamic object creation. What else do I need to do?
You can use Setter injection. The #Autowired annotation can be used on setter methods. In the below example, when the annotation is used on the setter method, the setter will be called with the instance of FooFormatter when FooService is created:
public class FooService {
private FooFormatter fooFormatter;
#Autowired
public void setFooFormatter(FooFormatter fooFormatter) {
this.fooFormatter = fooFormatter;
}
}
In this way you can inject you service when you call the setter method explicitly :) Hope this will help you :)
LATER EDIT
I've just found a way that might resolve your problem, it's named #Lazy.
You can use #Lazy annotation like this:
On your service class, put #Lazy annotation before the public Class XXX definition;
When declaring/autowiring a Service type in your controller context, put #Lazy annotation with #Autowired annotation on top of the declared attribute like
#Lazy
#Autowired
private FooFormatter fooFormatter;
for more info, check the link: http://www.baeldung.com/spring-lazy-annotation
You need to use #Lazy annotation with a combination of Bean Life Cycle annotations. But one thing you need to consider is the performance of your controller if you will re-create your service each time you need it, then you degradates the performance.
I have a spring config where I define hundreds of actions which extend MyAction. I have a pool where an execution service can look up actions. I can't use the appContext directly because each action has one or more "keys" which the execution service will use and pool cuts that dependency.
So the pool must be able to collect all beans of type MyAction (or rather beans that extend MyAction).
The method ApplicationContext.getBeansOfType() seems to do what I need but when can I safely call it?
It would be great if I could call it in a #PostConstruct method but is it guaranteed that the bean factory has seen added each and every bean from the config at that time?
Note: Almost all of my beans are #Lazy
You could use injection by constructor and passing a Collection of yours MyAction
Something like
#Component
public class Foo {
private final Set<MyAction> myActions;
#Inject
public Foo(Set<MyAction> myActions) { this.myActions = myActions; }
}
or
public class Foo {
private Set<MyAction> myActions;
#Inject
public void setMyActions(Set<MyAction> myActions) { this.myActions = myActions; }
}
Spring will take care of creating the set with all beans that extends MyAction.
In the first case, they are injected by constructor, you can safely use them in any method.
In the second case, Spring will eventually call the setter. You can either do any post processing in the setter or add a #PostConstruct method that works on myActions.
Try to use ListableBeanFactory like this. Also here is API documentation. Method getBeansOfType has parameter allowEagerInit which forces eager init of lazy object.
I use spring roo to build project and it's annotation driven, and there is no bean definition in XML file. All the configuration info is in *.aj file.
And now I want to set up an init method for a bean which don't have a default constructor (that bean is from the third party and it has a constructor with arguments, and I cannot remove them or give a default constructor to it.)
Is there anyone who can tell me how to do this, please?
The reason I want to do this is because I want to use applicationContext.getBean("thatBeanName") to dynamically get the bean and use it. Because the bean don't have a default constructor, I always get the error: java.lang.NoSuchMethodException: com.to.that.bean.<init>() and this is why I want to add the init-method to the bean.
Use #PostConstruct as shown in below example. It is equivalent to init-method="initialize()"
#PostConstruct
public void initialize() {
messages.put("English", "Welcome");
messages.put("Deutsch", "Willkommen");
}
#Bean(initMethod="init")
public MyBean getMyBean() {
...
}
In spring container it is "init" method that being called the last,
#postconstruct called before afterPropertiesSet. so it is safer if someone miss use.
"Multiple lifecycle mechanisms configured for the same bean, with different initialization methods, are called as follows:
1.Methods annotated with #PostConstruct
2.afterPropertiesSet() as defined by the InitializingBean callback interface
A custom configured init() method
[https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-java-lifecycle-callbacks][1]
Although, today I would prefer to be more Spring independent and use either #Postconstract, or even configure default init method recognition. to have only meaningful method name indicate that it should be used for initialization - clear from frameworks, clear from annotations.
As #Pangea has put in , #PostConstruct is the best choice. You could also implement initializingBean and do the initialization in afterPropertiesSet method .Check here for this approach.
I realized that there have been multiple answers trying to solve the problem. But with the newly introduced #Configuration which is popularly used within Spring Boot. Things are changed a little bit.
If you are using #Bean annotation in #Configuration annotated class like:
#Configuration
class FooClass {
#Bean
public Bar bar() {
return new Bar();
}
}
If you want to use an automatically called method on the bean instance during initialization, you have two options below:
Option1:
#Configuration
class FooClass {
#Bean(initMethod="init")
public Bar bar() {
return new Bar();
}
}
Option2:
#Configuration
class FooClass {
#Bean
public Bar bar() {
Bar bar = new Bar();
bar.init();
return bar;
}
}
BUT, as is explain in #Bean Java Doc here:
/**
* The optional name of a method to call on the bean instance during initialization.
* Not commonly used, given that the method may be called programmatically directly
* within the body of a Bean-annotated method.
* The default value is {#code ""}, indicating no init method to be called.
*/
The second is regarded as a better answer. See link here
I am using prototype scoped bean definitions in my Spring XML descriptors to configure the default properties (these beans have many properties) and then I call the application context with a getBean(beanName, ctorArgs[]) to create instances.
The bean definitions require 2-3 constructor arguments that supply logically unique keys used for things like key properties for the JMX ObjectName etc. Additionally, the variables that the constructor arguments are written to are final.
What I am seeing is that when the application context refreshes, it attempts to instantiate these prototypes, which seems completely the opposite of what you want prototypes to do. They're templates, not actual instances. To work around this, I have been configuring the prototypes with bogus ctor values so these bogus bean instances are instantiated and I simply filter out the created MBeans later in the code.
My question is, how do I configure the application context to register these prototype bean definitions, but not instantiate them until I make a getBean call ?
UPDATE:
The problem is a bit more complicated than I initialy thought. In fact, lazy is the default behaviour for prototype-scoped beans. I digged a bit and I managed to reproduce your problem and find the solution. So what is the problem?
You probably have <aop:scoped-proxy/> enabled or (#ComponentScan(scopedProxy=...) equivalent). During context refresh Spring wraps your prototype bean (ClosedMetricSubscriberFeed) with scoped proxy. It uses class proxy because (a) class proxies are chosen or (b) the class has no interfaces.
The class-based proxy is basically a CGLIB subclass of your bean that must call (due to JVM rules) a base class's constructor. And CGLIB generated class always calls no-arg constructor.
I know this sounds complicated, here's what you can do:
Disable <aop:scoped-proxy/>. Just like that.
Provide a dummy no-arg constructor and deprecate it just in case. Unfortunately you will have to discover such bogus instances manunally. Note that in this case the class will be of type: ``.
Extract an interface from your class and use interfaces for scoped proxies:
.
#Scope(
value = ConfigurableBeanFactory.SCOPE_PROTOTYPE,
proxyMode = ScopedProxyMode.INTERFACES)
Old answer:
Use lazy initialization with #Lazy annotation or lazy-init="true" (see 4.4.4 Lazy-initialized beans in reference documentation) configuration attribute.
<bean id="proto" class="MyPrototype" scope="prototype" lazy-init="true"/>
or:
#Service
#Scope("prototype")
#Lazy
public class MyPrototype {/*...*/}
I use a private, deprecated, no-arg constructor that throws an IllegalStateException. The context loads fine, getBean() with the constructor args works fine, and getBean() without args throws the exception.
package a;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
#Component("myCommand")
#Scope("prototype")
public class Command {
final protected String name;
#Deprecated
private Command() {throw new IllegalStateException("Only for Spring"); }
public Command(String name) {
super();
this.name = name;
}
#Override
public String toString() {
return "Command [name=" + name + "]";
}
}
After going thru autowiring concept
i have got some questions. These are:-
If i need to autowire below class byType or byName , is it mandatory to have setStudent() method in class College?
public class College {
private Student student1;
private String registration1;
}
<bean id="student1" class="Student"/> - in case of byname it will look into id attribute and in case of bytype it will look for class attribute in above
Stetement. Right? If incase it finds two bean dean tags for the same type it will throw fatal error in case of bytype. Correct?
autodetect Scenario chooses constructor or byType through introspection of the bean class. If a default constructor is found, the byType mode
will be applied.
My question here if default constructor is not found and constructor with argument is found then autowire by constructor
will be applied. Correct?
Do we need to specify #Autowired somewhere in College to apply the autowiring. As i can see this in this example
but nothing is specified here
1), 4) There are two separate ways of autowiring in Spring: XML-based and annotaion-based.
XML-based autowiring is activated from XML config, as described here. In the end, it will call setter method, so setStudent() method is required here.
Annonation-based autowiring, on the other hand, is performed via reflection magic. It attempts to fill everything you mark with #Autowired annotation. In fact, it can set private field with no accessors, as in
public class Foo {
#Autowired private Thingy thing; // No getThing or setThing methods
private void doStuff() {
// thing is usable here
}
}
For #Autowired annotaion to work, you will need to define corresponding bean post-processor; it is done by adding the following line to xml config:
<context:annotation-config/>
Note, that these two autowiring methods are independant, and it is possible(but not recommended) to use them simultaneously. In that case, xml autowiring will override annotations.
2) In general, autowiring will fail, if it cannot find one and only one candidate for injection. So, in your case, it will fail with exception upon container creation. There are some fallback quirks, but in general it works reliably.
3) Yes, documentaion says so.
About byName and byType autowiring. While byName autowiring simply tries to match bean name (can be specified with id attribute), byType is a bit more complex than class attribute lookup. It searches beans by type, and it will match interfaces. Example:
public interface SomeService {
void doStuff();
}
public class SomeServiceImpl implements SomeService {
#Override public void doStuff() {
// Implementation
};
}
public class ServiceUser {
#Autowired
private SomeService someService; // SomeServiceImpl instance goes here
}
P.S. You are referencing two different versions of Spring in your question, 2.5 and 3.0. Autowiring behavior is same in both.
In Addition if you are using #Autwired annotation you need to mark the classes as candidates for autowiring. It should be done by using one of these annotations:
#Repository
#Service
#Component
#Controller
and of cause you can configure it in different scopes:
#Scope("prototype")
#Repository
public class MovieFinderImpl implements MovieFinder {
// ...
}
Hope it makes it more clear.