In a Spring Boot application written in Kotlin it is possible to use both the init block or the #PostConstruct JSR-250 lifecycle annotation to do something right after instantiation. What are the consequences of using one vs the other in a #Component ? Can there be any behavioral difference?
Similar question here.
As you said:
do something right after instantiation.
init block gets executed during the instantiation. Therefore, the postconstruct annotation would be the right way to go, no matter whether you have injected beans or not.
An init block is pure Kotlin and has nothing to do with Spring.
#PostConstruct is a way to initialize after the Bean has been created an all dependencies are injected.
So if you want to access injected beans, you MUST use #PostConstruct.
For all other cases, you can use the init block or a constructor.
Related
I'm experimenting with examples from this official Spring tutorials and there is a dependency on this code:
https://github.com/spring-guides/gs-async-method/tree/master/complete
If you look at the code on AppRunner.java class, I have 2 questions:
When server is starting, if I put a breakpoint in this class's constructor, seems like in the constructor, the GitHubLookupService is provided by spring, using the #Service bean that was configured. BUT, there was no #Autowired annotation on the constructor, so how in the world this constructor get called with the right dependency? It was supposed to be null.
Is it an automatic assumption of Spring Boot?
Does Spring see "private field + constructor argument, and it assumes it should look for an appropriate bean?
Is it Spring Framework or Spring boot?
Am I missing something?
As I remember, it was mendatory to provide default constructor to beans / service etc. How come this class (AppRunner) doesn't have a default constructor?
How does Spring knows that it should run the constructor with the argument?
Is it because it is the only constructor?
Starting with Spring 4.3, if a class, which is configured as a Spring bean, has only one constructor, the #Autowired annotation can be omitted and Spring will use that constructor and inject all necessary dependencies.
Regarding the default constructor: You either need the default constructor, a constructor with the #Autowired annotation when you have multiple constructors, or only one constructor in your class with or without the #Autowired annotation.
Read the #Autowired chapter from the official Spring documentation for more information.
Think of it this way... Suppose you have the following component:
#Component
public class FooService {
public FooService(Bar bar) { /*whatever*/ }
}
When Spring is scanning this class, it wants to know how it should go about constructing an instance. It's using reflection so it can get a list of all of the constructors at runtime.
In this case, it is completely unambiguous how Spring must construct this instance. There's only one constructor so there is no decision to be made, and no ambiguity at all.
If you add #Autowired here, you are not narrowing anything down, and you are not giving Spring any extra information to help make its decision - its decision is already made because there is only one candidate.
And so, as a convenience, the Spring team decided #Autowired should be optional. Since its not helping the Spring framework to make a decision, its presence is just noise.
If your component has multiple constructors then you can use #Autowired on one of them to tell Spring "use this one, not that one".
is it possible to inject spring beans into a polling filter class (FClass) controlled by a scheduler job?
i don't quite understand how singleton applies here.
i understand spring beans are singleton so in order to inject the spring beans into class FClass. i need to define FClass as a bean and add the DI as property etc..
so how do i know if FClass should be a singleton? i assume only classes that are singletons can be created and beans and have DI done to them.
my problem is :
i need to be able to inject my facade bean xfacade into FClass. x_facacde handles the dao object. it has Y_dao and a Z_hibernate session beans injected as DI.
when i tried to create a spring bean of StatusPollingFilter (FClass) and injected the facade bean - i got a null and the setter is never called for the injection in debug mode.
the problem:
i'm thought it might be something to do with the thread / scheduler nature of StatusPollingFilter, and since spring beans are singletons it might not work due to that.
i'm thinking of creating a factory for the StatusPollingFilter (FClass). but need to know if this is correct thing and i'm on right track before i do too much work and realize even that doesn't work as the problem might be somewhere else. ideally i just want to update a table in the easiest possible way. but i have to use hibernate as the DAO exists but hibernate is configured using
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
with /hibernate/TopoObject.hbm.xml
files.
so no matter how i try this i always get null pointer exception on session or injected facade bean.
reading some of the QA's here seems like because StatusPollingFilter is instantiated using the scheduler and not spring it cant be aware of the DI beans. so would the above factory pattern help here.
I may have an additional problem but i'll cross that bridge when i come to it. but just to mention briefly, in case anyone is aware of issues that i might hit ... not sure what / how the scheduler would invoke the factory for an instance as its all controlled by 3rd party api - which invokes a StatusPollingFilter but i'm assuming if i pass in the factory as the class and parameter it would find its way through... but initial part is the main question. please ignore the latter waffle. thanks in advance.
Actually :
i assume only classes that are singletons can be created
is where you are wrong.
A bean is just a class that you let spring instantiate. By default, they are created as singleton but you can specify the scope on your bean using the attribute scope (quite surprisingly). The value you can specify are those specified in the documentation here
So one thing you have to be careful with is the injection of beans scoped as prototype or request into singletons.
having read more - i have come across the ans.
because the StatusPollingFilter object is under control of scheduler (i knew that scheduler had something to do with it) then it is unaware of the spring beans which is why i keep getting null when i try injecting the bean.
i created a class:
ApplicationContextProvider implements ApplicationContextAware
added static access
private static ApplicationContext appContext;
did a setter for it :
public void setApplicationContext(ApplicationContext context)
{
appContext = context;
}
and added
public static Object getBean(String beanName) throws BeansException
{
return appContext.getBean(beanName);
}
used in code as :
EvoTAMDAOFacade evoDao = (EvoTAMDAOFacade) ApplicationContextProvider.getBean("evoDaoFacade");
i now have access to the facade bean and all injected beans into facade.
i still have an issue with hibernate session but thats prob due to some other issue.
pt here is i don't have access to the bean as its not in control of the spring container so i needed to somehow get it , probably could have done it via the factory method but why mess around when there a simpler way.
thanks for help by anyone who may have posted or tried to understand my problem.
As in the title above, I am confused about pros cons between injecting applicationContext by directly #Autowired annnotation or implementing ApplicationContextAware interface in a singleton spring bean.
Which one do you prefer in which cases and why? Thanks.
Actually, both are bad. Both of them tie your application to the Spring framework, thus inverting the whole inversion-of-control concept. In an ideal world, your application should not be aware of being managed by an ApplicationContext at all.
Once you have chosen to violate this principle, it doesn't really matter how you do it. ApplicationContextAware is the legacy version that has been around at least since Version 2.0. #Autowired is a newer mechanism but they work in pretty much the same way. I'd probably go with ApplicationContextAware, because it semantically makes clear what it is about.
As #Sean Patrick Floyd says, the need of ApplicationContext is often due to a bad design. But sometimes you have no other option. In those cases I prefer the use of #Autowired because is the way I inject all other properties. So, if I use #Autowired for injecting MyRepository, why can't I use it for ApplicationContext or any other Spring bean?
I use Spring interfaces only for those things I can't do with annotations, for example BeanNameAware.
If you need to get a prototype in a singleton then you can use method injection. Basically, you create an abstract method that returns the object you need and spring will return the prototype everytime you call that method. You define the "lookup-method" in your spring config. Here are some links:
http://docs.spring.io/spring/docs/1.2.9/reference/beans.html#beans-factory-method-injection
http://java.dzone.com/articles/method-injection-spring
Since you are not extending any of the spring classes your application is always separated from the framework. Most of the cases you will not wanted to inject the ApplicationContext as it, but will need to inject the beans defined in the ApplicationContext.
The best case is always to stick to the bare minimum, until and unless you have any specific requirement and this is very simple with spring.
So either,
Annotate your beans and scan them in application context, then use #Autowire to wire them up.
Use application context to wire your bean expediencies(old xml style configs). You can use #Autowire with this approach also.
When you want to control the bean life cycle, you can read the API and customize it, but most of the time these general settings will do the job.
Here are some examples.
Spring Auto-Wiring Beans with #Autowired annotation
Spring Auto-Wiring Beans XML Style
Spring IoC container API Docs
There is no need to use ApplicationContext at all.
ObjectFactory
If you need to use prototype scoped beans in a singleton bean, inject an org.springframework.beans.factory.ObjectFactory.
For example using constructor injection:
#Service
class MyClass {
private ObjectFactory<MyDependency> myDependencyFactory;
public MyClass(ObjectFactory<MyDependency> prototypeFactory) {
myDependencyFactory = prototypeFactory;
}
}
Why
Now what's the benefit over using ApplicationContext ?
You can substitute this dependency (e.g. in a test) by simply passing a lambda (since ObjectFactory is a #FunctionalInterface) that returns a stubbed version of it.
While it is possible to stub the ApplicationContext, it is not clear in that case which beans will be looked up and need to be stubbed.
Is it possible to specify another bean to inject in case that the first intended bean to be injected fails?
Lets say we have Bean1, Bean2, and Bean3. Bean1 requires Bean2 but if Bean2 fails to be injected for some reason, then I want Bean3 to be injected instead. But each time Bean1 is retrieved from the container, it should always try to inject Bean2 first before attempting to inject Bean3. Is this possible? If not, what are my options?
Per me the question is flawed. In normal circumstances, Spring is supposed to be used for injecting the beans declaratively. So as pointed out by #Don Roby, #Adrian Shum the problem you are trying to solve is not for Spring.
Spring is not designed to resolve the dependency for you dynamically like a Service Locator.
This is a question to understand spring internals. There are a couple of workarounds suggested for self injection of a bean in spring because #Autowired doesn't work. Here are few threads. I would like to know the reason why and how does self injection work technically with #Resource annotation?
#Service(value = "someService")
public class UserService implements Service{
#Resource(name = "someService")
private Service self;
}
Any links to the spring source code would be appreciated. Thanks.
From another thread I got a response which seems fairly ok. Basically it states that spring specially adds defensive checks for handling #Autowired beans but #Resource beans bypass it and hence it works.
I don't know how exactly spring handles it, but here are a few options (the CDI specification uses these for example):
incomplete instances. When beans are instantiated and put in the context, their status is set as 'incomplete' - that is, their instance exists but their dependencies are not injected. Thus, first beans are instantiated, put in the context, and on the next stage their dependencies are injected. This makes the above case trivial - the container first create the instance and then, for each injection point, gets the desired bean from the context - itself, in this case
proxies. A proxy is created for each bean, so that it has beans without actually having instantiated the beans. It creates the proxies (by interface/concrete class), injects them into one another, and passes proxies around when needed. Finally each proxy gets its actual bean. This is perhaps not the case above, because this is used by CDI to handle circular constructor injection.