Spring dependency injection for multiple classes - java

I am new to Spring and I want to start using dependency injection.
I have many classes, and they hold dependencies as interfaces references, which I populate with objects I send as parameters to the constructor.
I know I can configure each class separately to inject each dependency with a specific implementation, but that means if I want to change the implementation of a specific dependency to all classes then I need to change every class, I want to be able to do that in one place for all classes.
What is the best way to do that?

In your class you will inject the interface:
public class Foo {
#Autowried
private Boo boo;
}
Then you will control which implantation gets added to the spring container :
#Service
public class BooImpl implements Boo {
}
Now all you need to do is change the implementation.
If possible I would use Spring Boot, you can download the examples and run the straight away https://spring.io/guides/gs/spring-boot/

Related

Why do we need to use beans in spring boot? [duplicate]

This question already has answers here:
What in the world are Spring beans?
(14 answers)
Closed last month.
I am just getting started with spring boot and I don't get why would I use beans instead of creating my own objects. what is the difference between an object that I created and the one spring created(bean)?
I tried making a bean and it takes more coding than creating a normal object, I had to learn how to use ApplicationContext,getBean etc..
Short answer: Spring bean = object.
Long answer: It's easier to allow Spring to inject all of your objects into the classes that depend on them, rather then creating your own IoC container.
Read more about it here: https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/beans.html
#Bean annotation is basically used to define your class as Object yes you re right that creatiing a bean initally requires a more coding that directly creating a object of the class but have you ever think suppose you have created the object by using new keyword and you have created this object at many places suppose 1000 places and if you have to change anything in your object that will complicate you because you have to go all 1000 places and change it but when you are using bean you need to make those change at single place and at all other places it will be reflectd automatically also in this case we donot need to compile your whole code that's why we use #bean also it will be very helpfull to make your code losselly coupled
Spring is a framework that allows you to use dependency inject. This means that the framework can build class instances (beans) for you and you simply declare the dependencies between the beans. I suggest you to get familiar with dependency injection.
#Bean
public class SuperHeavyService {
// the datasource is build by the framework due to configuration
private Datasource connection;
private HttpClient client;
//
public SuperHeavyService(Datasource connection, HttpClient client) {
this.connection = connection;
this.client = client;
}
}
#Bean
public class HttpClient {
}
The example above shows you that the SuperHeavyService is created by the framework and the framework will inject the requires types using the constructor of the SuperHeavyService class. This is dependency injection.
We use bean mainly to achive loose coupling.
When you are creating objects by yourself, then these objects are tight coupled.
Imagine an application with dozens or even hundreds of classes. Sometimes we want to share a single instance of a class across the whole application, other times we need a separate object for each use case, and so on.
Managing such a number of objects is nothing short of a nightmare. This is where inversion of control comes to the rescue.
Instead of constructing dependencies by itself, an object can retrieve its dependencies from an IoC container. All we need to do is to provide the container with appropriate configuration metadata.
With the IOC, you can achieve loose coupling.
Loose coupling means that classes are mostly independent. If the only knowledge that class A has about class B, is what class B has exposed through its interface, then class A and class B are said to be loosely coupled. In order to over come from the problems of tight coupling between objects, spring framework uses dependency injection mechanism with the help of POJO/P model and through dependency injection its possible to achieve loose coupling.
Example : If you change your shirt, then you are not forced to change your body – when you can do that, then you have loose coupling. When you can’t do that, then you have tight coupling. The examples of Loose coupling are Interface, JMS.
Java program to illustrate loose coupling concept
public interface Topic
{
void understand();
}
class Topic1 implements Topic {
public void understand()
{
System.out.println("Got it");
}
} class Topic2 implements Topic {
public void understand()
{
System.out.println("understand");
}
} public class Subject {
public static void main(String[] args)
{
Topic t = new Topic1();
t.understand();
}
}
Explanation : In the above example, Topic1 and Topic2 objects are loosely coupled. It means Topic is an interface and we can inject any of the implemented classes at run time and we can provide service to the end user.
Hope it helps.

Why Spring DependsOn annotation cannot use to auto wire an interface

When I'm working on write some spring code, I'm using spring 4 with class and annotation-config. I have declared a bean implements an interface as a component. And I'm trying to make another bean to depends on it with its interface time. But it doesn't work because spring throws an error with no bean found in that name. I think it may because depends on is only work with concretive class auto wire, but I don't know why it set in this way? Is anyone could explain why depends on annotation don't allow type auto wire to an interface?
The simple sample code is like this
#Component
class A implement B{
}
#Component
#DependsOn("B")
class C {
}
the code above cannot work unless I change
#DependsOn("B") to #DependsOn("A")
In general DependsOn should never be used. If you ever need to it, you have probably done something wrong, or you have an extreme corner case. I have used Spring since 2006 and have not needed it yet.
The JavaDoc says
Used infrequently in cases where a bean
does not explicitly depend on another through properties or constructor arguments,
but rather depends on the side effects of another bean's initialization.
This basically means you only use DependsOn if you or some one else have written bad code. For instance one beans constructor creates a resource on disk that another bean needs when constructed. Springs IoC container and declarative wiring lets you control dependencies between beans, but in the extremely rare case where some legacy code has undeclared dependencies DependsOn lets you control the order unrelated spring beans are constructed.
For simple autowiring, use #Autowired either on field or constructor. Starting with Spring 4.3 you can omit the #Autowired when using constructor injection.
#Component
class A implement B {
}
#Component
class C {
private final B b;
public C(B b) {
this.b = b;
}
}
I had same problem when I tried to used depends on, but after doing my research I found that the best way is to remove the dependency of B in class C constructor and use this logic in a method init annotated by #PostConstruct, so after initializing all the constructors this method will be executed.
Hope my answer helps you.

Java inject implementations from multiple modules using TypeLiteral

I have an issue with multiple implementations of interface, or rather with injecting them as a List.
This question is a direct follow up for question:
Java inject implementation using TypeLiteral
so I will refer havilly to those examples and refer to their solutions.
I have an interface:
public interface IImplementMe {
public String getValue();
}
and
I have multiple implementations of the IImplementMe interface from different modules of my project binded:
register(IImplementMe.class).annotatedWith(Names.named("someName")).to(SomeImplementation.class);
Everything zipped into list in module
private static class CustomTypeLiteral extends TypeLiteral<List<IImplementMe>> {
}
bind(new CustomTypeLiteral()).toRegistry();
And there are two assumptions (that makes this story different from linked question)
I do not know too much about implementations of IImplementMe, in particular if they are Singletons (I can force it if really needed)
They are binded in different modules not managed by me directly (and i don't want to bind those implementations myself)
Similarly, I want to inject a List of all of them in #Singleton class and call them whenever needed.
#Singleton
class SomeEndpoint {
#Inject
public SomeEndpoint(final List<IImplementMe> implementations){
///
}
}
And the question is: Is it guaranteed that Guice will pick up all implementations ? I know that they won't be available in constructor(the list will be empty) but after that the list should be refreshed as I understand Guice. I'm most concerned about scenario where implementations are not Singletons and they are not used anywhere else beside my class that injects List(SomeEndpoint in the example) (I'm worried that they'll never be initialized so never added to the list).
One additional thought: I'm not using Multibinder(I would like to avoid it if possible since I don't want to force other users to use it aswell, it will be a bit clearer if they could just register #Named implementation of IImplementMe it theirs modules).

DI with arguments in the constructor

So I'm implementing a Dependency Injection framework into my Java project (Google Guice) and everything is pretty good, I like it but there's a small problem;
I want to make a static instance of my main project's class (where it instantiates the dependencies, etc). But I don't know any method to instantiate it using Guice, I can't instantiate it manually because I'm using DI in the constructor of it (I have objects in the constructor) which means that I am not able to access the class' non-static variables needed to instantiate the class.
I tried using a Provider but I couldn't really understand where to bind it, because I don't want to have an interface for the main class (will if needed).
If you are wanting to mix a static instance of a class with dependency injection, you have somewhat missed the point of dependency injection: you can simply inject the instance of the class.
If you want there to be a single instance of a class for your injector, bind it in #Singleton scope: either:
bind(YourClass.class).in(Singleton.class);
in your module's configure() method, or
#Provides #Singleton YourClass provideYourClassInstance() {
// ...
}
in your module, or
#Singleton class YourClass {
// ...
}
in the actual class declaration.
Then just inject this instance like any other:
class SomeOtherClass {
#Inject SomeOtherClass(YourClass instance) {
// ... Do something with instance, like assign it to a field.
}
}
The point is that SomeOtherClass shouldn't need know anything about the lifetime of instance: it simply doesn't matter whether this is a singleton instance, or every class using it has its own instance.
You can get three different answers here depending on the question.
To directly answer the question in the title (DI with arguments in the constructor), you can mix DI with constuctor arguments by instead injecting a Factory. Though you're welcome to write one manually, Guice can do this for you as assisted injection (see FactoryModuleBuilder), or you can use the equivalent code-generated solution AutoFactory popular through Dagger.
If you're trying to initialize a static class's fields in a Guice application, Guice can do that for you as soon as the Injector is created. Simply call requestStaticInjection in a Module you feed to Guice. This, as Andy Turner pointed out, will cause you to miss out on some of the benefits of Guice: Because you're injecting the instance statically, there's very little opportunity for you to provide replacement implementations in tests or in other class reuse. Guice describes this more in the static injections section of its wiki:
When migrating an application from static factories to Guice, it is possible to change incrementally. Static injection is a helpful crutch here. It makes it possible for objects to partially participate in dependency injection, by gaining access to injected types without being injected themselves. [...]
Static members will not be injected at instance-injection time. This API is not recommended for general use because it suffers many of the same problems as static factories: it's clumsy to test, it makes dependencies opaque, and it relies on global state.
The best overall solution is in Andy's answer: Adapt your application to use DI, which will let it inject the objects that you would otherwise make static.

How to Inject a Function inside a set of classes

I have a usecase where i want a particular class or a spring bean to be injected in a set of classes that have a particular annotation. Basically i want a few set of methods to be added to the annotated classes.
Suppose i have a class annotated with annotation #Finders. Then i want the class to be able to use some predefined methods like
findById(), findByName() etc to be available to the class and we should be able to call these functions in a static context like
User.findById() and so on.
Is there a way to inject these methods to the class using Java or Spring. Can i use reflection to do this.
Is there any other way i can get this done in java.

Categories