In an interview, I have been asked a Question:
In spring, what is the use of an ApplicationContextAware interface ?
Performing Dependency injection
Makes bean aware of the container
Both of these
None of these
As per my knowledge, as well as per few articles , I think Option 2 is correct.
Please let me know if ApplicationContextAware interface also helps in Performing Dependency injection.
According to Docs, Its main/only goal is that class which is implementing this interface requires access to a set of collaborating beans.
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContextAware.html
I think the interface's name is self explanatory, so yes it makes the bean aware of the container.
The dependency injection is performed by the framework through multiple ways, but most of them use the #Autowired annotation, so you could start reading about it.
Related
What's the recommended way to run a spring boot test where only the one subject under test is configured in the context.
If I annotate the test with
#RunWith(SpringRunner.class)
#SpringBootTest(properties = "spring.profiles.active=test")
#ContextConfiguration(classes = MyTestBean.class)
Then it seems to work - the test passes, the context starts quickly and seems to only contain the bean that I want. However, this seems like an incorrect use of the #ContextConfiguration(classes = MyTestBean.class) annotation. If I understand correctly the class that I reference is supposed to be a Configuration class, not a regular spring service bean or component for example.
Is that right? Or is this indeed a valid way to achieve this goal? I know there are more complex examples like org.springframework.boot.test.autoconfigure.json.JsonTest which use #TypeExcludeFilters(JsonExcludeFilter.class) to control the context - but this seems overkill for my use case. I just want a context with my one bean.
Clarification
I know that I can just construct the one bean I am testing as a POJO without a spring context test and remove the three annotations above. But in my precise use case I am actually reliant on some of the configuration applied to the context by settings in the application-test.properties file - which is why I've made this a Spring Boot test with a profile set. From my perspective this isn't a plain unit test of a single class in isolation of the spring context configuration - the test is reliant on certain configuration being applied (which is currently provided by the spring boot app properties). I can indeed just test the components as a POJO by creating a new instance outside of a spring context, I'm using constructor injection making the providing of necessary dependencies simple but the test does rely on things like the log level (the test actually makes assertions on certain logs being produced) which requires that the log level is set correctly (which is currently being done via logging.level.com.example=DEBUG in a properties file which sets up the spring context).
For starters, reading the documentation first (e.g., the JavaDoc linked below in this answer) is a recommend best practice since it already answers your question.
If I understand correctly the class that I reference is supposed to be
a Configuration class, not a regular spring service bean or
component for example.
Is that right?
No, that's not completely correct.
Classes provided to #ContextConfiguration are typically #Configuration classes, but that is not required.
Here is an excerpt from the JavaDoc for #ContextConfiguration:
Annotated Classes
The term annotated class can refer to any of the following.
A class annotated with #Configuration
A component (i.e., a class annotated with #Component, #Service, #Repository, etc.)
A JSR-330 compliant class that is annotated with javax.inject annotations
Any other class that contains #Bean-methods
Thus you can pass any "annotated class" to #ContextConfiguration.
Or is this indeed a valid way to achieve this goal?
It is in fact a valid way to achieve that goal; however, it is also a bit unusual to load an ApplicationContext that contains a single user bean.
Regards,
Sam (author of the Spring TestContext Framework)
It is definitely a reasonable and normal thing to only test a single class in a unit test.
There is no problem including just one single bean in your test context. Really, a #Configuration is (typically) just a collection of beans. You could hypothetically create a #Configuration class just with MyTestBean, but that would really be unnecessary, as you can accomplish doing the same thing listing your contextual beans with #ContextConfiguration#classes.
However, I do want to point out that for only testing a single bean in a true unit test, best practice ideally leans towards setting up the bean via the constructor and testing the class that way. This is a key reason why the Spring guys recommend using constructor vs. property injection. See the section entitled Constructor-based or setter-based DI of this article, Oliver Gierke's comment (i.e. head of Spring Data project), and google for more information. This is probably the reason you're getting a weird feeling about setting up the context for the one bean!
You can also use ApplicationContextRunner to create your context using a test configuration of your choice (even with one bean if you like, but as other people have already mentioned for one bean it's more reasonable to use the constructor the classical way without using any spring magic).
What I like this way of testing is the fact that test run very fast since you don't load all the context. This method is best used when the tested bean doesn't have any Autowired dependencies otherwise it's more convenient to use #SpringBootTest.
Below is an example that illustrates the way you can use it to achieve your goal:
class MyTest {
#Test
void test_configuration_should_contains_my_bean() {
new ApplicationContextRunner()
.withUserConfiguration(TestConfiguration.class)
.run(context -> {
assertThat(context.getBean(MyTestBean.class)).isNotNull();
});
}
#Configuraiton
public static class TestConfiguration {
#Bean
public MyTestBean myTestBean(){
new MyTestBean();
}
}
}
Are #InjectParam (com.sun.jersey.api.core.InjectParam) and #Autowired (org.springframework.beans.factory.annotation.Autowired) same?
In one of the project, I have seen both of these are being used for similar purposes, hence I guess both can do the same job.
I am just wondering if my guess is correct or I am missing some critical catch out there.
I would appreciate if someone can explain the difference and which one to use under what situation?
Thanks.
Both #InjectParam and #Autowired are used for dependecy injection purposes.
According to the documentation, Jersey's #InjectParam is used to annotate fields, methods or parameters that shall be injected with instances obtained from Jersey or registered IoC component provider factories that provide support for Guice, Spring or CDI.
Spring's #Autowired is used to perform injections in the Spring Framework and, as far as I know, it won't work in Jersey resources.
From this post #Autowired not working on jersey resource , it seems #Autowired does not work with Jersey resource in which case we have to use #InjectParam for Jersey resouce.
I am reading the Spring Hibernate CRUD tutorial from this url
http://viralpatel.net/blogs/spring3-mvc-hibernate-maven-tutorial-eclipse-example/
Please can anyone tell me why in ContactController.java, ContactService interface is autowired instead of the class ContactServiceImpl.
Similarly in ContactServiceImpl ContactDAO interface is injected. Shouldn't we supposed to inject class instead of an interface?
When your code is dependent on interface and its implementation is injected by Spring, your code becomes decoupled with the implementation. This has an advantage that now you can swap in a different implementation without having to change the code that makes use of interface.
Spring is smart. It will find the implementation of the interface and inject it appropriately (or a proxy thereof.)
You should be programming to interfaces, not implementations.
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.
Does it makes sense in Spring to use #Autowired to wire directly to a concrete class and not to an interface (and make use of 'by type' autowiring)
If a class doesn't implements an interface wouldn't it be better to instantiate it via constructor or a factory (keeping things simple); rather than make it a Spring bean just for the heck of it.
Does it makes sense in Spring to use #Autowired to wire directly to a concrete class and not to an interface
Sure. The practice of autowiring is independent of what you're autowiring. It'll work with classes just as well as interfaces.
However, whether or not it's a good idea is debatable, although this is a more general question of whether you should always introduce an interface for a given class, rather than talk directly to the class type. The benefits include easier unit-testing and a cleaner design, at the expense of code clutter.
There's another good reason to autowire interface types rather than class types, which is that if Spring needs to generate a proxy object around the bean before injecting it, then if the bean's class defines any interfaces, then the proxy will implement those interfaces, and will not be type-compatible with the bean class itself. If you then try and autowire that bean by class type, it will fail. The easiest way to avoid this annoying scenario is to always autowire by interface type, that way it will lways work as you expect.
and make use of 'by type' autowiring
If you mean container-level byType autowiring, then you don't want to do that. It's the old Spring 1.x style of autowiring, and it's highly inflexibile (see limitations of autowiring).
Stick with #Autowired, it's much more flexible and easier to control.
If a class doesn't implements an interface wouldn't it be better to instantiate it via constructor or a factory (keeping things simple); rather than make it a Spring bean just for the heck of it.
The two questions are completely separate. An object should be made a Spring bean if you need Spring to control its dependencies and lifecycle, regardless of whether or not it implements interfaces. If you find that the object has no dependencies, and no meaningful interface, then perhaps there is no reason to make it a bean.
You will have to decide if hardwiring this dependency into other classes is ok. For instance, how many different classes are likely to require this dependency? If the answer is many then you will be creating many instances of this class where only one is required.
Also, what dependancies does this concrete class have? You will have to configure those inside the class that depends on it.
The object of dependency injection is to reduce the dependencies between classes and make your code loosely coupled.