I am working on a Spring MVC project where I am dealing with different types of services,Repositories i.e classes annotated with #Service and #Repository. I am confused with a couple of questions:
When to use #AutoWired annotation?
I have seen various repositories using this:
CourseRepository crepo=new CourseRepository();
and I have seen this also
#AutoWired
private CourseRepository crepo;
Which one of the above options should be used to get an instance of
repository in Service class?
Can I use #AutoWired for classes which are not annotated with #Repository or
#Service?
I am a beginner in this java world.Any help will be highly appreciated.
Thanks
You use new for data objects, which in most modern architectures are passive (they're not "active records"). Everything else is a service object, and you should inject those. (The one place that you do use new is with an #Bean method, which is a "factory" that creates the service object; in this case you normally pass the dependencies as method parameters.)
Note that it is recommended to use constructor injection instead of field injection; it makes your code easier to test, and it eliminates the possibility of certain kinds of errors. In fact, if using constructor injection, it's not required to have any Spring annotations in your service classes at all; beans can be registered using #Import instructions or #Bean methods on a configuration class.
You should #Autowire the dependencies instead of instantiating it yourself. Doing so, service and repo layer will be loosely coupled. Moreover, a mock repository can be easily injected in service's JUnit test class if dependency is autowired. To conclude, use below:
#Autowired
private CourseRepository crepo;
A class not annotated with any of below stereotype annotations will not be in Spring's IoC (Inversion of Control) container. Hence, no point in autowiring in a class that is not annotated with any of below annotations.
#Component, #Controller, #Service, #Repository
Dependency injection means that the framework is the one who handles the classes instantiation and the object of that class is going to be injected (thanks to #Autowired annotation) in the class where you need it. In other words, you do not need to instantiate service and repository classes by yourself using new operator, you just need to tell the framework that those classes need to be injected and that's why you use #Autowired annotation.
Related
This question already has answers here:
Understanding Spring #Autowired usage
(3 answers)
Closed 6 years ago.
Using Spring, i have a class 'BaseController' with BaseService injected using autowiring. How the autowiring working even if the class is not inititalized. Check code below
#Controller
class BaseController{
#Autowired
private BaseService baseService;
//......
}
and bean definition in xml as
<context:annotation-config />
<bean name="baseService" class="com.test.service.BaseService" />
I am not initializing baseService either with Setter/Constructor.
How does it works, when i call a method as show below
baseService.methodOne();
Spring framework relies on Spring IoC (Inversion of Control) Container to create all the components and initialize them by injecting their dependencies. The dependencies are injected though constructors, setters and/or fields by using the reflection API.
Here you annotated the field baseService with the annotation Autowired which will indicate the Spring IoC Container to inject a bean of type BaseService, if at the time the container needs to create your Controller, the dependency has not been created and initialized, it will do it automatically and if this bean has dependencies it will apply the same logic on the dependencies until the dependency tree has been fully created and initialized. This is how it works in a nutshell.
If we have two controller classes A & B, with dependency on
BaseService. Does Spring container create two objects and injects into
A and B separately or Only one instance of BaseService is shared among
all the classes that has dependency.
It depends on the scope that you set on your bean declaration, if the scope is singleton, the container will create only one instance of your bean and then will inject the same instance in your controllers. If you chose prototype for example, it will create a new instance of your bean for each of your controllers. In your case knowing that singleton is the default scope, it will inject the same instance. For more details about the supported scopes in Spring IoC Container, you can read this.
If you have enabled the class scanning, spring detects all the spring bean types at the startup and inject dependencies if it marked with #Autowired, #Resource, etc annotations.
According to your example, BaseController must be a type of spring bean and also the BaseService. If the BaseService is an interface there must be an impl. if there are many impls, then you need a #Qualifier annotation as well.
Spring uses reflection, so you do not need a setter or a constructor to inject the dependency.
By default all the beans are singleton unless you set scope via #Scope
I have a Spring 3 project which acts as a Rest API, and wanted to wire a spring bean I have into an unmanaged class for logging purposes.
After trying many different things, what worked was marking my unmanaged class with the annotation #Configurable.
Like:
#Configurable
public class ClassNotManagedBySpring {
#Autowired
#Qualifier("myBean")
private MyBean myBean;
}
#Service("myBean")
public class MyBean {
#Autowired
#Qualifier("someOtherBean")
private SomeOtherBean someOtherBean;
}
And then in my beans.xml:
<context:spring-configured/>
So now let's say that ClassNotManagedBySpring.java, is one of 6 classes that all do something similar, except 3 of them ARE managed by spring because they have the #Component annotation.
But all 6 of these classes need to #Autowire MyBean.java and only some need the #Configurable annotation.
To note, I was already previously using AspectJ in this app for multiple other purposes.
I want to know what is the risk in my spring application by all of a sudden wiring spring managed dependencies into un managed classes in this way?
Can there be performance issues? Risks of errors at runtime?
If this isn't the best way of wiring a spring managed bean into an unmanaged class, what is?
I've been using #Configurable for years without issues, it's a very easy solution if you need app instantiated beans configured by Spring. My use cases were all in the UI tier. I also used #Configurable(preConstruction = true) whenever I needed autowired values already in the constructor. Of course, if you make millions of #Configurable objects it might be a performance issue, otherwise I wouldn't worry too much about it. The only small aesthetic problem I had was Eclipse giving me some red underlines at class definitions extending #Configurable classes, complaining that the hierarchy of class SomeClass is inconsistent, but it compiled them nevertheless, no errors in the Problems view or at runtime whatsoever.
I have this interface:
public interface liteRepository extends CrudRepository<liteEntity, Long>, JpaSpecificationExecutor<liteEntity> {...}
It works, all is well.
However, intellij does not register this class as a spring component. If I annotate this interface with #Component, then intellij recognizes this as a spring bean and I can #Autowire this repository in my integration tests.
My code still works after annotation, but I'm not confident that I am not messing with things that I should not be messing with.
Question:
Is there any harm in adding the #Component annotation to this interface?
The only thing that #Component annotation means is that the class is eligible for becoming a Spring bean during Spring's component-scan.
So, if you want it to be a Spring bean and you did not define it as a Spring bean anywhere else, you can safely add the #Component annotation.
Of course, this will only work if you have the actual component scan configured somewhere(for, example <context:component-scan base-package="..."> in some Spring config file), which I am assuming you already heave, since the bean is properly getting autowired after you add the annotation.
I am going through some blogs on SpringSource and in one of the blogs, author is using #Inject and I suppose he can also use #Autowired.
Here is the piece of code:
#Inject private CustomerOrderService customerOrderService;
I am not sure about the difference between #Inject and #Autowired and would appreciate it if someone explained their difference and which one to use under what situation?
Assuming here you're referring to the javax.inject.Inject annotation. #Inject is part of the Java CDI (Contexts and Dependency Injection) standard introduced in Java EE 6 (JSR-299), read more. Spring has chosen to support using the #Inject annotation synonymously with their own #Autowired annotation.
So, to answer your question, #Autowired is Spring's own annotation. #Inject is part of a Java technology called CDI that defines a standard for dependency injection similar to Spring. In a Spring application, the two annotations works the same way as Spring has decided to support some JSR-299 annotations in addition to their own.
Here is a blog post that compares #Resource, #Inject, and #Autowired, and appears to do a pretty comprehensive job.
From the link:
With the exception of test 2 & 7 the configuration and outcomes were
identical. When I looked under the hood I determined that the
‘#Autowired’ and ‘#Inject’ annotation behave identically. Both of
these annotations use the ‘AutowiredAnnotationBeanPostProcessor’ to
inject dependencies. ‘#Autowired’ and ‘#Inject’ can be used
interchangeable to inject Spring beans. However the ‘#Resource’
annotation uses the ‘CommonAnnotationBeanPostProcessor’ to inject
dependencies. Even though they use different post processor classes
they all behave nearly identically. Below is a summary of their
execution paths.
Tests 2 and 7 that the author references are 'injection by field name' and 'an attempt at resolving a bean using a bad qualifier', respectively.
The Conclusion should give you all the information you need.
To handle the situation in which there is no wiring, beans are available with #Autowired required attribute set to false.
But when using #Inject, the Provider interface works with the bean which means that the bean is not injected directly but with the Provider.
The key difference(noticed when reading the Spring Docs) between #Autowired and #Inject is that, #Autowired has the 'required' attribute while the #Inject has no 'required' attribute.
As of Spring 3.0, Spring offers support for JSR-330 dependency injection annotations (#Inject, #Named, #Singleton).
There is a separate section in the Spring documentation about them, including comparisons to their Spring equivalents.
Better use #Inject all the time. Because it is java configuration approach(provided by sun) which makes our application agnostic to the framework. So if you spring also your classes will work.
If you use #Autowired it will works only with spring because #Autowired is spring provided annotation.
#Autowired annotation is defined in the Spring framework.
#Inject annotation is a standard annotation, which is defined in the standard "Dependency Injection for Java" (JSR-330). Spring (since the version 3.0) supports the generalized model of dependency injection which is defined in the standard JSR-330. (Google Guice frameworks and Picocontainer framework also support this model).
With #Inject can be injected the reference to the implementation of the Provider interface, which allows injecting the deferred references.
Annotations #Inject and #Autowired- is almost complete analogies. As well as #Autowired annotation, #Inject annotation can be used for automatic binding properties, methods, and constructors.
In contrast to #Autowired annotation, #Inject annotation has no required attribute. Therefore, if the dependencies will not be found - will be thrown an exception.
There are also differences in the clarifications of the binding properties. If there is ambiguity in the choice of components for the injection the #Named qualifier should be added. In a similar situation for #Autowired annotation will be added #Qualifier qualifier (JSR-330 defines it's own #Qualifier annotation and via this qualifier annotation #Named is defined).
In addition to the above:
The default scope for #Autowired beans is Singleton whereas using JSR 330 #Inject annotation it is like Spring's prototype.
There is no equivalent of #Lazy in JSR 330 using #Inject.
There is no equivalent of #Value in JSR 330 using #Inject.
#Inject has no 'required' attribute
#Autowired(required=false)
By default the dependency injection for #Autowired must be fulfilled because the value of required attribute is true by default. We can change this behavior by using #Autowired(required=false). In this case if bean is not found for dependency injection, it will not through error.
Please have look at
https://www.concretepage.com/spring/spring-autowired-annotation#required-false
But #Inject doesn’t need (required=false) it will not through error if dependency is not found
The #Inject annotation is one of the JSR-330 annotations collection. This has Match by Type,Match by Qualifier, Match by Name execution paths.
These execution paths are valid for both setter and field injection.The behavior of #Autowired annotation is same as the #Inject annotation. The only difference is the #Autowired annotation is a part of the Spring framework. #Autowired annotation also has the above execution paths. So I recommend the #Autowired for your answer.
I have an app that's been working well with #Autowired #Service beans.
Now I'm adding a Validator class which is instantiated in the Controller:
BlueValidator validator = new BlueValidator(colors);
validator.validate(colorBlend, bindResult);
In the BlueValidator class I'm trying to #Autowire the blendService which is working as an #Autowired field elsewhere in the app:
public class BlueValidator implements Validator {
#Autowired
private BlendService blendService;
private Colors colors;
But for some reason after instantiating the BlueValidator, I keep getting NullPointerExceptions for the blendService.
Of course I've added the necessary context scanning:
<context:component-scan
base-package="com.myapp.controllers, com.myapp.services, com.myapp.validators" />
I also tried adding the#Autowired annotation to the constructor but that didn't help:
#Autowired
public BlueValidator(Colors colors) {
this.colors = colors;
}
Should I just pass the blendService to the BlueValidator and forget about the Autowiring or is there something obvious missing here?
If you just instantiate an object with new, Spring is not involved, so the autowiring won't kick in. Component scanning looks at classes and creates objects from them - it doesn't look at objects you create yourself.
This can be made to work, using Spring's AspectJ support, but it takes some effort.
Otherwise, you need to let Spring instantiate your objects if you wan autowiring to work.
Should I just pass the blendService to the BlueValidator and forget about the Autowiring
In your situation, I'd say yes, this is the least effort solution.
When you instantiate objects spring cannot do anything for them, so it does not get the dependencies injected (article).
In your case, you have a couple of options:
pass dependencies to the validator from the controller (where you can inject them)
make the validator a spring bean and inject it, instead of instantiating it
use #Configurable, which, via AspectJ, enables spring injection even in objects created with new
#Autowired is being used by Spring's ApplicationContext to populate those fields on creation. Since the ApplicationContext is not the one creating these beans (you are because of the keyword 'new'), they are not being autowired. You need to pass it in yourself if you are creating it.
Don't create validator manually -- allow to Spring do this work for you:
#Controller
class Controller {
#Autowired
BlueValidator validator;
void doSomething() {
...
validator.validate(colorBlend, bindResult);
...
}
}
Also pay attention that adding package com.myapp.validators to context:scan-packages not enough, you also should annotate your validator class with #Component annotation:
#Component
public class BlueValidator implements Validator {
#Autowired
private BlendService blendService;
(BTW this solution works in my project.)