Spring #Autowired
I have a doubt on Spring #Autowired annotation.Please Help...
In Spring mvc ,when I tried #Autowired in this order
Controller--->Service--->Dao
ie,In Controller I autowired Service Class Object , In Service Class Autowire Dao Object.
This Injection chain works perfectly.
Similliarly In strutrs2+Spring ,I applied #Autowired Annotation in this way
Action--->Service-->Dao
This Injection chain also works fine.
If I call a funtion from outside this chain (eg:Custom Taglib class (from jsp)) to funtion in Service class Then in this Service class the Autowired dao object is null(ie,this call braks the chain).
My questions is
Is this #Autowired works in a Injection chain Only?
Beans that have #Autowired fields only have them set if they are sent through the Spring Bean Postprocessor -- that is, like you said, if you autowire them yourself. That is a big reason that constructor injection is much more preferred than field injection. Instead of doing
#Service
public class MyService {
#Autowired
private MyDao dao;
...
}
you should do
#Service
public class MyService {
private final MyDao dao;
#Autowired
public MyService(MyDao dao) {
this.dao = dao;
}
}
That way, when you're in a situation where you can't rely on a service to be post-processed (as in your case of using the jsp tag library), you can simply instantiate a new instance with a MyDao object and be on your merry way.
Related
public abstract class CommonBillService implements BillService {
#Autowired
#Qualifier("onlineProfitServiceImpl")
private ProfitService profitService;
....
}
#Service
public class OnlineProfitServiceImpl implements ProfitService {
#Autowired
#Qualifier("aBillServiceImpl")
private BillService aBillService;
}
#Service
public class ABillServiceImpl extends CommonBillService implements Move {
....//inject other services or dao here with #Autowired,
//there is no OnlineProfitService here explicitly, but its parent CommonBillService inject OnlineProfitService by autowired
}
this code works under spring boot 2.1.2, but failed with circular reference under 2.1.3:
Error creating bean with name 'aBillServiceImpl':
Bean with name 'aBillServiceImpl' has been injected into other beans [onlineProfitServiceImpl]
in its raw version as part of a circular reference, but has eventually been wrapped.
This means that said other beans do not use the final version of the bean.
but my code has no constructor injection, i just use #Autowired to inject, so it is not possible to throw circular reference, right?
I following my teacher but i have some confused. This is a interface extends CrudRepository from Spring data
import org.springframework.data.repository.CrudRepository;
public interface TaskRepository extends CrudRepository<Task,Integer>{
}
and this is class Service use that interface:
#Service
#Transactional
public class TaskService {
private final TaskRepository taskRepository;
public TaskService(TaskRepository taskRepository) {
this.taskRepository = taskRepository;
}
public List<Task> findAll(){
List<Task> tasks = new ArrayList<>();
for(Task task : taskRepository.findAll()) {
tasks.add(task);
}
return tasks;
}
}
I confused that when an Controller want to use instance of TaskService. It just declare like this:
#Autowired
private TaskService taskService;
Who can explain me how it work? The init of TaskService have TaskRepository as argument. but I don't find any where init TaskRepository
Once you mark your class with #Component or any variation of it such as #Service/#Repository/#Controller, you delegate it's object management to spring.
By doing
#Autowired
private TaskService taskService;
you are telling spring that, while creating an object of the controller, first create the object of TaskService and assign it to taskService variable declared in the controller.
Then spring will try to create object of TaskService but while creating, it sees the constructor
public TaskService(TaskRepository taskRepository) {
this.taskRepository = taskRepository;
}
So, it will now try to create object of TaskRepository because without that, TaskService object can't be created.
Now, TaskRepository is an interface that extends CrudRepository and interfaces cannot be instantiated. Spring creates a proxy that implements TaskRepository, creates the object and injects it into taskRepository of the TaskService constructor.
So far, spring has built the TaskRepository, TaskService objects. It will simply inject TaskService object into autowired taskService variable of the controller.
Spring boot will automatically initialize JPA Repositoriy interfaces if found.
By default, Spring Boot will enable JPA repository support and look in the package (and its subpackages) where #SpringBootApplication is located. If your configuration has JPA repository interface definitions located in a package not visible, you can point out alternate packages using #EnableJpaRepositories and its type-safe basePackageClasses=MyRepository.class parameter.
https://spring.io/guides/gs/accessing-data-jpa/
In addition since Spring Framework 4.3 if there is a single constructor it will be attempted for autowiring.
https://spring.io/blog/2016/03/04/core-container-refinements-in-spring-framework-4-3
For your example you can omit the #Autowired for your constructor, because your Service has only one constructor.
JPA Repositoriy interfaces, TaskRepository will be automatically initialized by spring boot.
I'm writing unit test case using Junit, EasyMock and Spring. I'm trying to mock DAO layer call. I've used annotation to inject bean in my application
Service layer class:
public class CustomerService {
#Autowired
private CustomerDao customerDao;
........
public void findCustomerByAccountNumber(String accountNumber){
}
}
Test case for service method:
public class CustomerServiceTest extends AbstractContextConfigLoaderTest{
private CustomerDao mockCustomerDao;
private CustomerService customerService;
private String accountNumber="5247710009575432";
#Before
public void setUp(){
mockCustomerDao= EasyMock.createMock(CustomerDao.class);
customerService= new CustomerService();
}
if i would have used setter injection using Spring bean configuration, i would've set mocked dao object to customerService like below.
customerService.setCustomerDao(mockCustomerDao);
How can i do the same in case of Spring annotation ?
You can use still setup a method
protected void setCustomerDao(CustomerDao customerDao)
and only use it in your JUnit to set the mocked dependencies. The protected access will prevent any class that is not in the same package from using that method.
I suggest enabling spring in your test with something like #RunWith(SpringJUnit4ClassRunner.class) and #ContextConfiguration, in your spring context for the test
make the mock as spring bean.
<bean class="org.easymock.EasyMock" factory-method="createMock">
<constructor-arg value="some.package.CustomerDao" />
</bean>
Now should be wired to the CustomerService, to record the expected behavior you will need to wire the mock in your test class:
#Autowired
private CustomerDao mockCustomerDao;
#Autowired
private CustomerService customerService;
Why not expose this through the constructor and inject it that way? Your production code can use Spring and your test code can just instantiate the object directly.
At the moment you're at the mercy of your DI framework. Break that dependency.
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.
I am using Spring for my DI.
Is there an equivalent of #ManagedProperty? I want to inject the value from one view scoped bean into another one on the next page.
e.g
#Component
#Scope("view")
public class Page1Bean(){
private String value;
}
#Component
#Scope("view")
public class Page2Bean(){
#ManagedProperty(value = #{page1Bean}") //doesnt work in Spring
private Page1Bean bean;
}
#Resource or #Autowired should work. #Resource is the Java EE implementation, #Autowired is the spring specific annotation. I can't find the reference now, but it seems like I read once to prefer #Resource over #Autowired.
here's a blog post I found that talks about #Inject vs. #Resource vs. #Autowired
http://blogs.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/#more-2350