I have a BaseDaoImpl class, it has following method:
#Autowired
public void initSessionFactory(#Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
super.setSqlSessionFactory(sqlSessionFactory);
System.out.println("------ ok ------");
}
I defined a subclass UserDaoImpl, which implements BaseDaoImpl. And defined it as a bean.
When init Spring context, I found that the initSessionFactory() method is executed automatically, but I didn't call any methods.
In my understanding, the method is executed & autowire its params only when I call it, can someone help to explain how it works? Thanks.
That behavior is normal. Your initSessionFactory method annotated with #Autowired is considered to be a config method. #Autowired can be placed on constructors, fields and methods. When the bean is created, first the constructor is called, then the fields are injected and then config methods are called.
A config method's (annotated with #Autowired) arguments will be autowired with a matching bean in the Spring container.
See the Javadoc API for Autowired annotation for more details.
Related
I'm learning about dependency injection in Spring and I have this code:
#Autowired
private CamelContext context;
#Autowired
private Environment environment;
#Autowired
protected CamelContext createCamelContext(){
return context;
}
...
}
I understand that context and environment bean is injected in this class, but what I don't understand is what exactly is injected with this code:
#Autowired
protected CamelContext createCamelContext(){
return context;
}
I don't understand this kind of injection. What exactly is happen here? What is the difference between this method injection and this simple method without injection:
protected CamelContext createCamelContext(){
return context;
}
Any feedback will be apreciated! Thank you!
Methods annotaded with #Autowired are either setters or config methods. They are called after bean creation and can be used for initialization. All the arguments of these methods will be automatically injected by Spring. From Spring javadoc:
Autowired Methods
Config methods may have an arbitrary name and any
number of arguments; each of those arguments will be autowired with a
matching bean in the Spring container. Bean property setter methods
are effectively just a special case of such a general config method.
Such config methods do not have to be public.
But in your case createCamelContext() has no arguments and does no initialization either. So I don't see any reason to declare this method.
In this scenario, #Autowired is pretty much equivalent to #Bean on createCamelContext and #Inject on context. Autowiring beans occurs by type if you don't give a #Qualifier, so your code will basically take your #Autowired/#Inject CamelContext context and go looking for a CamelContext to fill in the missing value, which it will find as provided by #Autowired/#Bean createCamelContext.
The difference between an annotated createCamelContext and an un-annotated one is that Spring will not have that method in its Beans, and so it won't find the method when looking for a #Bean to #Inject.
In your specific case, the value context goes looking for a CamelContext, and finds one in the form of createCamelContext. At this point, createCamelContext looks up the value of context, which is null. It returns this value, which is injected into context. Therefore, at any point in time, referring to context or createCamelContext should always yield null.
This question already has answers here:
Difference between #Bean and #Autowired
(6 answers)
Closed 4 years ago.
What is the difference between #Bean and #Autowired in Spring?
As far as I understood we can use both to inject dependencies, #Autowired when the interface was implemented just in one class, and #Bean, when the interface was implemented in more than one class, in the last case #configuration, is required.
thanks in advance
In short #Bean is producer and #Autowired is consumer, #Bean annotation let spring know instance of this class and it hold for it and #Autowired annotation ask for please give me instance of class which we created with #Bean annotation.
more detailed answer find here
When you use #Bean you are telling to Spring that:
this is the object that I want you to put within your stack and later I will ask
about it from you
And When you use #Autowired you are telling to Spring that:
Now please give me the object that I already told you to keep it in your stack (means the #Bean object)
When you use #Bean you are responsible for providing an Id and calling that Id when you wish to use that particular object using getBean() method.
Autowired helps avoid the calling part and returns an object everytime it is needed. Spring handles the job of returning the appropriate object and helps reduce additional syntax for referring to a particular bean.
Spring provides a very nice documentation about Autowired and Bean API
#BEAN
#Target(value={METHOD,ANNOTATION_TYPE})
#Retention(value=RUNTIME)
#Documented
public #interface Bean
Indicates that a method produces a bean to be managed by the Spring
container.
On Bean #Target annotation confirms that it can be applied over a METHOD.
#AUTOWIRED
#Target(value={CONSTRUCTOR,METHOD,PARAMETER,FIELD,ANNOTATION_TYPE})
#Retention(value=RUNTIME)
#Documented
public #interface Autowired
Marks a constructor, field, setter method or config method as to be autowired by Spring's dependency injection facilities. This is an alternative to the JSR-330 Inject annotation.
On Autowired #Target confirms that it can be applied over a CONSTRUCTOR,METHOD,PARAMETER,FIELD.
IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies, that is, the other objects they work with, only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean.
I'm new to Spring, I would like to know:
I have a java class annotated with #Component (spring) and inside I have a method annotated with #PostConstruct. The class is then referenced by #Autowired annotated field in another class. Can I assume that the class is only injected after #PostConstruct is called?
#Component
class AuthenticationMetrics {
private static final MetricRegistry metrics = new MetricRegistry();
final Counter requestsTotal;
final Meter guestLogins;
final Meter kfUserLogins;
final Timer guestLoginResponseTime;
final Timer kfLoginResponseTime;
#PostConstruct
public void populateMetricsRegistry() {
metrics.counter("authentication.requests.totals");
}
}
If you are asking is injection of given class happening after #PostConstruct in that bean is called, then the answer is yes - #PostConstruct is executed before bean is considered as "injectable"
If you are asking if #PostConstruct on given bean is executed after all injections has been done (on the same bean) - then yes - #PostConstruct is executed after injections are commited to given bean. This is the reason it exists. Normally you could put #PostConstruct actions into the constructor. However, when new object is created (constructor is called) injections are not performed yet - so any initialization that depends on injected objects would fail due to NPE. That is why you need #PostConstruct
The handling of annotations such as #PostConstruct, #Resource, #PreDestroy is done via a BeanPostProcessor, in this case the CommonAnnotationBeanPostProcessor. You can see in the following diagram from Spring that these BPP's are handled after Dependency Injection but before Bean Ready For Use (Which means as much as injectable).
Yes. Bean creation workflow is:
constructior call
#Autowired fields
#Autowired setters
BeanPostProcessor's postProcessBeforeInitialization(), i.e. #PostConstruct called by CommonAnnotationBeanPostProcessor
InitializingBean.afterPropertiesSet()
BeanPostProcessor's postProcessAfterInitialization()
Bean is ready and can be injected to other bean
Is it possible to inject new instances of prototype scoped beans to Controller's method arguments at runtime using annotations in Spring? So whenever the method is called, Spring would inject the qualifying bean as its argument, familiarly as it injects #ModelAttribute. As far as I know, #Autowired fields are injected only once when context is created. Obtaining the bean from context's factory method isn't an option, as that would expose framework to its component, thus violating the hollywood principle.
I have almost completed reading Spring in Action book and have been reading Spring Reference a lot, but haven't found any info regarding this question.
You have a couple of options.
Define a prototype bean and inject that wrapped in an ObjectFactory
#Autowired
private ObjectFactory<PrototypeBean> factory;
You can then retrieve it in your handler method. For example
#RequestMapping("/path")
public String handlerMethod() {
PrototypeBean instance = factory.getObject();
instance.someMethod();
return "view";
}
Every time you call factory.getObject(), you'll get a new instance.
As for doing this directly, no, Spring MVC does not have a built-in feature for having beans injected while invoking handler methods, with #Autowired or otherwise.
However, the HandlerMethodArgumentResolver API allows you to define an implementation for any type of parameter you want. You can define a new annotation and use it to annotate the appropriate handler method parameter(s). The implementation would look for the annotation and resolve an instance from an injected ApplicationContext. You could do this by name, by type, however you want.
I am working on a simple Java EE application.
I have class like this:
import javax.annotation.PostConstruct;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
#Stateless
public class BlogEntryDao {
EntityManager em;
#PostConstruct
public void initialize(){
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Persistence");
em = emf.createEntityManager();
}
public void addNewEntry(){
Blogentry blogentry = new Blogentry();
blogentry.setTitle("Test");
blogentry.setContent("asdfasfas");
em.persist(blogentry);
}
}
So my managed bean calls this method. Until here no problems. But since the initialize method is not called, I am getting an NPE in em.persist.
Why is the initialize method not being called? I am running this on Glassfish server.
Regards.
The Java EE bean annotations such as #PostConstruct only apply to container-managed beans. If you are simply calling new BlogEntryDao yourself, the container isn't going to intercept the creation and call the #PostConstruct method.
(Furthermore, you'd be better off using #PersistenceContext or #PersistenceUnit instead of manually fetching the EntityManagerFactory in your initialize() method, and you should be creating an EntityManager for each call to addNewEntry(), since they're short-lived. Making these changes would eliminate the need for initialize() at all.)
I had the same problem in my application.
You didn't post your bean context configuration xml file (so I'm not sure if it's the same issue) but in my case adding this line:
<context:annotation-config/>
Solved my problem.
You need either <context:annotation-config/> or <context:component-scan/> to enable #PostConstruct annotation.
Since this question comes up first on Google for "postconstruct not called", another reason a #PostConstruct method might not be called besides using the new keyword instead of putting #PostConstruct in a Spring bean is if you have a circular dependency.
If this bean were to depend on another bean that depended on this bean, your other bean might call addNewEntry() before BlogEntryDao was initialized, even though BlogEntryDao is a dependency for that other bean.
This is because Spring didn't know which bean you wanted to load first due to the circular reference. In this case, one can remove the circular reference or use #AutoWired/#Value constructor parameters instead of member values or setters, or if using xml configuration, maybe you can swap the order in which the beans are defined.
In my case #PostConstruct was not called because my initialize() method was static and was also throwing an exception. In either case the method is ignored. I hope it helps someone else who made the same mistake.
This can be found in the console:
WARNING: JSF1044: Method '<XXX>' marked with the 'javax.annotation.PostConstruct' annotation cannot be static. This method will be ignored.
WARNING: JSF1047: Method '<XXX>' marked with the 'javax.annotation.PostConstruct' annotation cannot declare any checked exceptions. This method will be ignored.
When using Spring make sure you are using the right PostConstruct annotation from the right package.
javax.annotation.PostConstruct
should be the one. Not for example:
jakarta.annotation.PostConstruct
It took me a little while to figure out why only one of my PostConstruct didn't work.
In my case #PostConstruct method was not called because I was referencing to a public instance variable of the spring service bean directly in other service beans (ie myService.myProperty). When i made a public getter method for the property (ie getMyProperty()) and used that to get the property the #PostConstruct method was called again. Also I made myProperty private to prevent any accidental direct referencing in the future.
Also note that if you don't explicitly register the class with #Bean in a #Configuration annotated class and rely soley on #Autowired instead, the #PostConstruct method may not be executed immediately on startup. Only when one of the methods of the autowired class are referenced and called by another class will that class be loaded and only at that time will the #PostConstruct method be called. In other words, by only using #Autowired you are essentially lazy loading a class. If you want to load it at startup, register it with #Bean
Heres a good SO thread about the difference between #Bean and #Autowired Difference between #Bean and #Autowired
EDIT: One last remark. When you have a webapplication and decided to annotate your class with #RequestScope then the #Postconstruct annotated method will be called each time when a new request comes in. This is because #RequestScope instructs spring to create a new instance of the class every time a new request comes in. If you want all requests to use the same instance, then you could use #Bean as mentioned above, but you could also use the annotation #Singleton above your class. This will cause the class to be loaded eagerly upon startup.
Make sure the class having #Postconstruct method lies within the same package. I moved class file to main package and it worked.
In my case I had two instances of javax.annotation.PostConstruct inside classpath. One was bundled with the war package and another was provided by tomcat. When Spring is scanning for the #PostConstruct annotation it compares these two different instances. Therefore the #PostConstruct annotated method was not picked while scanning.
Providing only one instance of javax.annotation-api library solved the issue.
Since most of the ways are already mentioned. However one can also create a bean in the config file for the class
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
;
This will enable PostConstruct and PreDestroy annotations.
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"></bean>
Also for Predestroy one needs to call context.registerShutDownHook()