what is the purpose of spring boot autowired annotation on a constructor? - spring

what is the purpose of #Autowired annotation on a constructor? What is the difference between non-annotated and annotated constructor? Thank you.

Autowiring feature enables you to inject the object dependency implicitly.
Without autowiring you have to initiate the object like:
public class SomeOperation() {
private CarService carService;
public SomeOperation() {
carService = new CarServiceImpl();
}
}
But if you annotate with #Autowired you don't have to initiate the object. The framework will bring the class which implements the carService and initiate your object with it.
public class SomeOperation() {
private CarService carService;
#Autowired
public SomeOperation(CarService carService) {
this.carService = carService;
}
}

What is the difference between non-annotated and annotated
constructor?
In Spring 3 or below, the annotation on the constructor is mandatory to make Spring consider the constructor as the way to instantiate the bean and inject dependencies provided in parameters.
Spring 4 and above versions don't require the annotation to do that.
You just need to declare the constructor with any parameter to achieve that.
So in recent Spring versions, don't clutter the code with the annotation :
public Foo(Bar bar){
this.bar = bar;
}

Related

Autowiring of Service and Service Implementation class

Following are my code
#RestController
public class EmployeeController {
#Autowired
EmployeeService empService;
public EmployeeController (EmployeeService Impl empServiceImpl) {
super();
this.empService = empServiceImpl;
}
}
#Service
public interface EmployeeService {
public List<EmployeeDTO> getAllEmployeeDetails()
}
public class EmployeeServiceImpl {
public List<EmployeeDTO> getAllEmployeeDetails(){
//methods business logic and repo call goes here
}
}
When I start my server I am getting below error.
Parameter 1 of constructor in
com.app.in.controller.EmployeeController required a bean of type
'com.app.in.service.EmployeeServiceImpl' that could not be found
My understanding might be wrong. If I annotate the EmployeeSeriveImpl class also with #Service then it working.Is that is the correct way to do it ? My question is the service interface is annotated with #Service still why its implementation is also required to annotation. Please let me know if I miss something in that ? What is the standard method to solve this issue ?
You can get your dependency injected using a constructor. And #Autowired is optional in this case.
This is your example, but with a few corrections:
#RestController
public class EmployeeController {
// private final is a good practice. no need in #Autowire
private final EmployeeService empService;
// this constructor will be used to inject your dependency
// #Autowired is optional in this case, but you can put it here
public EmployeeController (EmployeeService empServiceImpl) {
this.empService = empServiceImpl;
}
}
I assume you have an interface EmployeeService and class EmployeeServiceImpl which implements that interface and is Spring Bean.
Something like this:
#Service
public class EmployeeServiceImpl implements EmployeeService {}
Why this #Service is needed? When you put this annotation on your class, Spring knows this is a bean that Spring should manage for you (container will create an instance of it and inject it wherever it is needed).
Check Spring docs to get more details about Dependency Injection.
The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null.

Use spring Transactional in a Prototype bean

I would like to use spring transaction management capabilities within a prototype bean. I did the following:
I've used javax.inject.Provider to create my prototype bean.
I've annotated the method of the prototyped bean with the #Transactional annotation.
Is this the right way of doing it?
#Service
public class SomeService {
#Autowired
private Provider<SomePrototype> myPrototypeProvider;
public void execute() {
SomePrototype somePrototype = myPrototypeProvider.get();
somePrototype.someMethod();
}
}
#Component
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class SomePrototype {
#Autowired
private SomeSpringBean someSpringBean;
#Autowired
private SomeRepository someRepository;
#Transactional(propagation = Propagation.REQUIRED)
public void someMethod() {
Result result = someSpringBean.doSomething();
someRepository.save(result);
}
}
The initialisation of transaction-scoped bean requires a proxy. Therefore, if we define a transactional bean as prototype, every that bean is requested, a new proxy is created, and that is not efficient.
What is reason behind this requirement (to have transactional prototype bean)

How to initialize List inside Object using Spring Annotation

How do I initialize List inside Object using Spring Annotation
#Component
class Accounts{
private List<Transaction> _transaction;
//getter setter
}
How do I initialize List<Transaction> _transaction; using Spring Annotation or else i
have to define it in xml file.
But i dont want to write any xml file
You can use the Spring Java #Configuration for such a task:
#Configuration
public class SpringConfig {
#Bean
public List<Transaction> transactions() {
...... //Your logic to generate the list..
return transactions;
}
}
And in your Accounts class you have to use #Resource, not #Autowired, the semantics of injecting a list is a little different - if you use #Autowired, any bean of the same type will get injected into the list.
#Component
class Accounts{
#Resource(name="transactions")
private List<Transaction> _transaction;
//getter setter
}
This is pure java solution and there is no xml involved in creating the list..
If Transaction is a Bean with #Service, #Component or #Repository Annotation, you can just write #Autowired on top of your field.
#Component
class Accounts{
#Autowired
private List<Transaction> _transaction;
//getter setter
}

Could not autowire field when bean implements some interface with Spring

I am using Spring in my Java Application, all the #Autowired annotations working until now.
Simplified example would be:
#Component
public class MyBean implements MyInterface {
...
}
#Component
public class MyOtherBean {
#Autowired
private MyBean myBean;
...
}
Once I try to start the Application, I get:
java.lang.IllegalArgumentException: Can not set MyBean field MyOtherBean.myBean to $ProxyXX
The interface contains just two public simple methods and the class implements them.
Both classes are public and have public default constructor. (I even tried to instantiate them in tests.
Once I remove the implements section, everything works correctly.
What can be wrong with the implementation of the interface? What is $ProxyXX?
I suspect the issue is that Spring is injecting an AOP proxy which implements MyInterface - possibly for the purposes of transaction management or caching. Are any of MyBean's methods annotated #Transactional or annotated with any other annotation?
Ideally you'd probably want to reference MyBean by it's interface type - which should resolve the issue.
#Component
public class MyOtherBean {
#Autowired
private MyInterface myBean;
...
}
If you have more than one bean implementing MyInterface then you an always qualify your bean by name.
#Component
public class MyOtherBean {
#Autowired
#Qualifier("myBean")
private MyInterface myBean;
...
}
By default, Spring uses Java dynamic proxies to implement AOP when the bean implements an interface. The easiest and cleanest way to solve your problem is to make program on interfaces, and inject theinterface insted of the concrete class:
#Component
public class MyOtherBean {
#Autowired
private MyInterface myBean;
...
}
See http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/htmlsingle/#aop-proxying for how to force Spring to always use CGLib.

Does a Spring annotated controller necessarily need a default constructor

I have a spring controller that uses annotations. I gave this controller a constructor that takes two arguments. I want both ways of initializing the controller: constructor injection and setter injection.
#Controller("viewQuestionController")
#RequestMapping("/public/viewQuestions")
public class ViewQuestionController
{
#Resource(name="questionService")
private QuestionService questionService;
/*public ViewQuestionController()
{
int i=0;
i++;
}
*/
public ViewQuestionController(#Qualifier("questionService") QuestionService questionService)
{
this.questionService = questionService;
}
#Resource(name="questionService")
public void setQuestionService(QuestionService questionService)
{
this.questionService = questionService;
}
}
When I uncomment the default constructor, the controller is initiated correctly. However, if I don't, I get a BeanInstantiationException, No default constructor found; nested exception is java.lang.NoSuchMethodException.
So, is my configuration for the annotated constructor wrong or does a completely annotated controller in spring always need a default constructor?
If you want to configure constructor injection via annotations, you need to put the corresponding annotation on the constructor. I'm not sure how it can be done with #Resource, but #Autowired and #Inject support it:
#Autowired
public ViewQuestionController(#Qualifier("questionService") QuestionService questionService)
or
#Inject
public ViewQuestionController(#Named("questionService") QuestionService questionService)
I think Controller beans need a default constructor as they are initialized by the framework but there is no way to tell the framework hot to provide the dependency.
On second thought why not you autowire your question service and Spring will take care of it.
The following code should be good
#Controller("viewQuestionController")
#RequestMapping("/public/viewQuestions")
public class ViewQuestionController
{
#Autowired
private QuestionService questionService;
//Not providing any constructor would also be fine
public ViewQuestionController(){}
questionService will be initialized properly by Spring

Resources