Proper way of injecting dependencies? - java

Which one is the best way of injecting my dependencies? Why?
What is the difference between the two?
public abstract class Service {
private IConfig config;
#Inject
public Service(IConfog config) {
this.config = config
}
}
Or
public abstract class Service {
#Inject private IConfig config;
#Inject
public Service() {
}
}

Constructor injection (1st) is preferred over setter injection given that it makes it easier to support "immutable" entities or entities whose behaviour is well defined and non-modifiable after construction. Constructor vs Setter inject
For me the rule of thumb is to first prefer constructor injection and jump off to setter injection if constructor inject requires me to bend my back i.e. when working with legacy code with "OOP getter and setter" methods.
EDIT: I'm assuming you are trying to decide between "constructor" and "setter" constructor. But it also seems that you are using abstract classes which can't be instantiated. Maybe you have something else in mind?

First of all, I do not put injection-related annotations in abstract classes - in my opinion there is no sense in deciding how something should be instantiated if it actually cannot be instantiated (of course that's only my opinion with which others may agree or not).
Usually I do it in the following way:
public abstract class AbstractService {
private IConfig config;
public AbstractService(IConfog config) {
this.config = config
}
}
public class Service extends AbstractService {
#Inject
public Service(IConfig config) {
super(config);
}
}
Now, you can use both classes with and without dependency injection (construct it by hand, passing all required references). Also you can be sure that Service is instantiated in the appropriate state every time.

The main goal of dependency injection is to make unit testing easy by allowing to do
Service serviceToTest = new Service(mockConfig);
or
Service serviceToTest = new Service();
serviceToTest.setConfig(mockConfig);
The second way of injecting dependencies makes it impossible to do the abover. You can only test it by letting Guice create the service and inject a mock dependency, or by using reflection to set the mock dependency.

Related

Does Spring dependency injection really make the goal loose coupling?

Spring is famous with it Inverse Control and DI.
I know that dependency injection have several ways like Constructor Dependency Injection etc.
for example
we usually use #Autowired annotation to do Dependency Injection.
when we develop MVC web project.
My question is very simple
Why is a spring framework loosely coupled?
Suppose We have two Dao class One is Dao1 ,other is Dao2
Dao1
public class Dao {
public void sayhi() {
System.out.println("hello");
}
}
Dao2
public class Dao2 {
public void saygoodbye() {
System.out.println("say goodbye");
}
}
If we do not use Autowired annotation
the service should be
public class Service {
Dao1 dao=new Dao1();
Dao2 dao2=new Dao2();
public void sayhi() {
dao.sayhi();
}
public void saygoodbye() {
dao2.saygoodbye();
}
}
and the Controller should be
#RestController
public class Controller {
Service service=new Service( );
#GetMapping("test")
public void saysomething() {
service.saygoodbye();
service.sayhi();
}
}
If we do not use Autowired annotation , we must use new keyword to make instance
If we use Autowired annotation
the code
Dao1 dao=new Dao1();
Dao2 dao2=new Dao2();
just change it into
#Autowired
Dao1 dao
#Autowired
Dao2 dao2
So,without Autowired annotation
Why is a spring framework loosely coupled?
If you use new keyword, then Service need to know how Dao1 and Dao2 are implemented and instantiated(concrete type, parameters...), more knowledge means more coupling.
However, if you use #Autowired, then Spring do everything for you by Dependency Injection technique, the coupling becomes more loosely.
The advantage of loosely coupling is: your code becomes more testable and maintainable.
You should read about the many benefits of dependency injection, this is a good place to start: https://en.m.wikipedia.org/wiki/Dependency_injection.
But if you want a short one line answer its main benefit is that it makes the code easier to test.
If you create the DAO classes with the new keyword in your service class you cannot easily replace them with mock objects during testing of the service class.
First, note that field injection has been discouraged by Spring for several years now. Second, dependency injection alone does not magically guarantee loose coupling. Abstraction is also necessary. Since there is no abstraction in these examples, Service is coupled just as tightly to the Dao implementations whether you inject or instantiate them.
Spring still offers other benefits here, including lifecycle management and cohesion. Also note that since the Dao classes are not final, there is potential for abstraction, because Spring could inject subclasses whereas direct instantiation will always give you the base class.

Jersey constructor with parameters

I want to use a DAO in my RESTful service developed with Jersey, so the DAO implementation should be injected via the constructor of the service:
#Path("eventscheduler)
public class EventSchedulerService {
private IEventSchedulerDao dao;
public EventSchedulerService(IEventSchedulerDao dao) { this.dao = dao; }
}
However, I know Jersey expects a default constructor to setup everything correctly. I have been trying to figure out how to do this for a while but surprisingly this seems to be an uncommon case, I wonder how people inject DAOs into their services, or deal with injection in general at all.
How can I do this?
If you're using Jersey 2, it uses HK2 as it's DI framework. All resource classes go through the DI lifecycle when they are constructed. And constructor injection is not a problem.
The most basic way (with Jersey) to make an arbitrary object injectable, is to bind in an AbstractBinder
public class Binder extends AbstractBinder {
#Override
protected void configure() {
bind(EventSchedudlerDaoImpl.class).to(EventSchedulerDao.class);
}
}
Then register the binder with Jersey
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(new Binder());
}
}
Then you just need to declare the injection point by adding #Inject on top of the constructor.
#Inject
public EventSchedulerService(EventSchedulerDao dao) {
this.dao = dao;
}
As far as the binder implementation, the binding syntax basically reads as
bind( Implementation ).to( Contract ).in( Scope );
The bind method can take an instance or it can take a class. When you provide an instance, the Scope is automatically Singleton.
The to method specifies the advertised contract, which is the type that can be declared at the injection point. In this case, only the interface EventSchedulerDao can be used for the injection point. If you don't have an interface you can just do
bindAsContract(EventSchedulerDao.class)
assuming EventSchedulerDao is the implementation class.
The scopes available are PerLookup, RequestScoped and Singleton. If not specified, the default scope will be PerLookup, meaning a new instance of the service will be created for each injection point. You should already know what Singleton means. RequestScoped means that a new instance will be created for each request, which may not be the same as PerLookup, as the service may be injected at multiple points through out the request lifeclyle.
See Also:
Dependency injection with Jersey 2.0
Custom Injection and Lifecycle Management
hk2 tagged questions. Alot of them are Jersey related.
You must annotate the class constructor (or the property itself) with javax.inject.Inject.
import javax.inject.Inject;
class EventSchedulerResource {
private final IEventSchedulerDao dao;
#Inject
public EventSchedulerResource(IEventSchedulerDao dao) {
this.dao = dao;
}
// ...
}
If the IEventScheduler is an interface you must create a configuration class class that extends org.glassfish.jersey.server.ResourceConfig and register the binding of interface to a concrete implementation with bind(EventSchedulerDaoImpl.class).to(IEventScheduler.class) (See here: https://jersey.java.net/documentation/latest/ioc.html chapter 23.1)

spring #Autowire property vs setter

What is the difference between anotate #Autowired to a property or do it in the setter?
As far as I know they both have the same result, but is there any reason to use one over the other?
UPDATE (to be more concise)
Is there a difference between this
package com.tutorialspoint;
import org.springframework.beans.factory.annotation.Autowired;
public class TextEditor {
private SpellChecker spellChecker;
#Autowired
public void setSpellChecker( SpellChecker spellChecker ){
this.spellChecker = spellChecker;
}
public void spellCheck() {
spellChecker.checkSpelling();
}
}
and this
package com.tutorialspoint;
import org.springframework.beans.factory.annotation.Autowired;
public class TextEditor {
#Autowired
private SpellChecker spellChecker;
public TextEditor() {
System.out.println("Inside TextEditor constructor." );
}
public void spellCheck(){
spellChecker.checkSpelling();
}
}
Sometimes you need an instance of class A, but you do not store A in the fields of the class.
You just need A instance to perform a one-shot operation. Or, you use A instance to obtain an instance of B, and you are storing B in the field.
In those cases, a setter (or constructor) autowire will suit you better.
You will not have unused class-level fields.
Concrete example:
You need to construct RabbitTemplate (an object that sends messages to RabbitMQ)
To construct it, you need ConnectionFactory
http://docs.spring.io/spring-amqp/docs/latest_ga/api/org/springframework/amqp/rabbit/core/RabbitTemplate.html#RabbitTemplate-org.springframework.amqp.rabbit.connection.ConnectionFactory-
You do not need to store that ConnectionFactory. In that case, code that looks like this:
Class MyClass {
private RabbitTemplate template;
#Autowired
void setConnectionFactory(ConnectionFactory c) {
template=new RabbitTemplate(c);
}
}
...will serve you better than directly autowiring the ConnectionFactory field.
In this example, autowiring at the constructor level would be even better, because your object will always be completely constructed. It will be clear that ConnectionFactory is a mandatory dependency, not an optional one.
With #Autowired annotation, you don't need a setter method. Once your bean's constructor is done with allocating/creating the object, Spring will scan for this annotation and would inject the object instances that you annotated.
While if you have setter and if you are still using xml config, you would explicitly set properties.
Having said that, You could annotate your constructor and setter method with autowired annotation which i would prefer as this would give me flexibility later on to move away from Spring (although i wont do it).
If you use #Autowired annotation on a property, spring will initiate the property using spring.xml. You don't need setter in this case.
If you use #Autowired annotation on a setter, you are specifying to spring that it should initiate this property using this setter method where you can add your custom code, like initializing some other property with this property.
Usage with Example:
In the case of using DAO operations using JdbcTemplate, you need DataSource as an input to JdbcTemplate, but DataSource is not required as a property in itself. So you can use DataSource Setter to initialize JdbcTempate by auto-wiring DataSource Setter. Please see the below code:
class DaoDemo{
//#Autowired
//private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
#Autowired
public void setDataSource(DataSource dataSource){
//this.dataSource = dataSource;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public int getTableRowCount(){
String sql = "SELECT COUNT(*) FROM DEMOTABLE";
//jdbcTemplate.setDataSource(dataSource); //No need to do this as its done in DataSource Setter now.
return jdbcTemplate.queryForObject(sql,Integer.class);
}
In the above code, the only use of dataSource was to get passed in JdbcTemplate. So, creating a property of dataSource doesn't make sense here. So, just use the #Autowired on setter method of DataSource bean to get its entry from spring.xml and make use of it at that particular time itself.
There are 3 types of autowiring:
Property based
#Autowired
private MyService service;
Constructor based. Note in Spring Boot you don't even need #Autowired annotation in this case:
class MyController {
private final MyService service;
public MyController(MyService service) {
this.service = service;
}
}
Setter based:
private MyService service;
#Autowired
public void setService(MyService service) {
this.service = service;
}
It is recommended to use Constructor based, then if not possible, Setter based and lastly Property based.
Why?
First, because in Constructor based you don't even use any Spring annotations. This helps you transition to different frameworks.
Second, Constructor or Setter based, make unit testing much easier. You don't need to use any Spring specific testing tools and you can only use Junit and Mockito.
Third, Constructor based is good because you can declare the property as final and not expose setters which helps with immutability and thread safety of the class.
Autowiring works best when it is used consistently across a project. If autowiring is not used in general, it might be confusing to developers to use it to wire only one or two bean definitions. With #Autowired on a field you don't need a setter method, which, on one hand makes the class smaller and easier to read, but on the other hand makes mocking the class a bit uglier.
Explicit dependencies in property and constructor-arg settings always override autowiring. You cannot autowire so-called simple properties such as primitives, Strings, and Classes (and arrays of such simple properties). This limitation is by-design.
Autowiring is less exact than explicit wiring. Spring is careful to avoid guessing in case of ambiguity that might have unexpected results, the relationships between your Spring-managed objects are no longer documented explicitly.
Wiring information may not be available to tools that may generate documentation from a Spring container.
Multiple bean definitions within the container may match the type specified by the setter method or constructor argument to be autowired. For arrays, collections, or Maps, this is not necessarily a problem. However for dependencies that expect a single value, this ambiguity is not arbitrarily resolved. If no unique bean definition is available, an exception is thrown.
If you can, you should avoid the setter. If you don't need it, it's better when it doesn't exists, right?
I personally prefer Guice allowing me to write
public class TextEditor {
private final SpellChecker spellChecker;
#Inject public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void spellCheck(){
spellChecker.checkSpelling();
}
}
This goes a step further: With a final field, I know it won't ever change and I get the multithreading visibility guarantee.
There is one case where using #Autowired on an OPTIONAL property would not work.
If you want to do some initialization using that property, it might not be set before the constructor is called, and since it is optional, you cannot put it as an argument in the constructor.
In that case it is better to use an #Autowired setter method, so you can perform the initialization once the property is autowired.

#Inject not injecting and causing NullPointerException using component scanning

My application context XML is simple:
<context:component-scan base-package="com.depressio.spring" />
In that package, I have my configuration:
package com.depressio.spring
#Configuration
#ComponentScan(basePackages = "com.depressio")
public class DepressioConfiguration
{
#Inject private ApplicationContext context;
}
Within com.depressio, there's a repository (DAO):
package com.depressio.dao;
#Repository
public class ParameterDAO
{
public Parameter getParameter(long ID) { ... }
}
... and a service where injection is working just fine (no NPE when parameterDAO is used):
package com.depressio.resource;
#Service
#Path("/depressio/parameters")
public class ParameterResource
{
#Inject private ParameterDAO parameterDAO;
#Path("{id}")
public Response getParameter(long parameterID)
{
return Response.ok(parameterDAO.getParameter(parameterID).legacyFormat()).build();
}
}
However, the legacyFormat() method call there constructs another object. Within that object, I have to inject a different DAO (also annotated with #Repository, though). That injection isn't working.
So, we have the original Parameter object:
package com.depressio.domain;
public class Parameter
{
...
public LegacyParameter legacyFormat()
{
return new LegacyParameter(this);
}
}
... and the LegacyParameter where the injection isn't working:
package com.depressio.domain.legacy;
public class LegacyParameter
{
#Inject private LegacyDAO legacyDAO;
....
public LegacyParameter(Parameter newParameter)
{
// NullPointerException when using the injected legacyDAO.
}
}
I've tried a few things, including:
Using an no-args constructor for LegacyParameter, then calling a populate method so I'm not using the injected DAO until after the object is constructed. This didn't work.
Injecting the LegacyDAO into the ParameterResource and passing it in. This worked, but isn't ideal since I have to pass it around a whole lot (which injection should help avoid, no?). It did prove that LegacyDAO is injectible... just not into LegacyParameter apparently.
Adding a #Service, #Component, or #Named annotation on LegacyParameter. All end up with the NullPointerException on the line I try to reference the injected legacyDAO.
What am I missing?
As Sotirios has pointed out, it can't work since you create a regular Java object and do not give Spring a chance to enhance it.
Either let Spring create objects for which you want to enjoy the Spring 'magic' (like setting #Inject dependencies etc).
Or create your own objects and set the dependencies yourself (yourObject.setDao(dao)).
That said, there are exceptional cases in which you still want to create your objects 'on the fly' by yourself but rely on Spring to inject dependencies to these objects. In this case you should call Spring explicitly:
LegacyParameter p = new LegacyParameter(...);
applicationContext.getAutowireCapableBeanFactory().autowireBean(p);
I don't think you really need it in your case.
(see this link inject bean reference into a Quartz job in Spring? for an example when this is really required).
In addition, I would advice to simplify your configuration.
Why do you use both xml-based and java-based configuration that do actually the same? In your example you could keep only one of them and have the same effect.

Injecting dependencies using #Autowired into objects created with "new ..."

I have a problem with injecting a bean into a helper class. It works basically like this: I create an object in the page constructor that does some work, returns some data and I show these on the page. In this helper object, a service should be injected via #Autowired annotation. However, I always get a null pointer exception when I use it. I also tried #SpringBean but it didn't help. On the other hand, when I inject this service directly into the page with #SpringBean, it's accessible and works fine. Do you know where the problem is?
This is the page:
public class Page extends BasePage {
public Page() {
HelperObject object = new HelperObject(new Application("APP_NAME"));
String result = object.getData();
add(new Label("label", result));
}
}
Helper object:
public class HelperObject {
private Application app;
#Autowired
private Service service;
public HelperObject(Application app) {
this.app = app;
}
public String getData() {
// use service, manipulate data, return a string
}
}
You can inject dependencies into non-Spring-non-Wicket-new-created objects using #SpringBean by calling InjectorHolder.getInjector().inject(this); in its constructor.
For example:
class MyPojo {
#SpringBean
MyDumbDAO dao;
MyPojo() {
InjectorHolder.getInjector().inject(this);
}
void justDoIt() {
dao.duh(); // dao is there!
}
}
Note that it will only work if called within a Wicket-managed request. If not (ie, if it's a Quartz job, or a Filter executed before Wicket's), the Application instance will not be available, and the injector won't know how to get the dependencies.
Another solution is to use Spring's #Configurable. It uses AspectJ to intercept creation of annotated objects, and inject its dependencies, even if you instantiate them directly with new (or some other framework, like Hibernate, creates them internally). But this requires runtime or build-time (works better for me) bytecode manipulation, which may be too much magic for some people.
#SpringBean only injects dependencies into classes that inherit from Wicket's Component. #Autowired only injects dependencies into classes created by Spring itself. That means you can't automatically inject a dependency into an object you create with new.
(Edit: you can also add a #SpringBean injection to your class by injecting in the constructor:
InjectorHolder.getInjector().inject(this);)
My normal workaround for this is to use my application class to help. (I'm a little puzzled by your use of new Application(...). I assume this isn't actually org.apache.wicket.Application.) For example:
public class MyApplication extends AuthenticatedWebApplication implements
ApplicationContextAware {
private ApplicationContext ctx;
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.ctx = applicationContext;
}
public static MyApplication get() {
return (MyApplication) WebApplication.get();
}
public static Object getSpringBean(String bean) {
return get().ctx.getBean(bean);
}
public static <T> T getSpringBean(Class<T> bean) {
return get().ctx.getBean(bean);
}
....
}
In my Spring application context:
<!-- Set up wicket application -->
<bean id="wicketApplication" class="uk.co.humboldt.Project.MyApplication"/>
My helper object then looks up the service on demand:
public class HelperObject {
private Service getService() {
return MyApplication.getSpringBean(Service.class);
}
The best practice would be to create your objects via a factory bean (that has those properties injected by Spring, and have that factory inject those properties to objects it spawns - pure IoC).
You should really avoid using SpringContext all over the place (or any other similar solution for that matter).
Here is a partial list of reasons:
Your code gets coupled with Spring way too much (low-cohesion).
You mix plumbing code with the business-logic.
Your code is less readable.
It's less maintainable (e.g., changing the name of the service bean would lead to code modification - this violates SRP & OCP).
It's less testable (e.g., you need the Spring framework to test it).

Categories

Resources