Why Spring DependsOn annotation cannot use to auto wire an interface - java

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.

Related

initialize an instance without any field in spring

I am trying to apply ioc into a school project. I have an abstract class Application without any field
public abstract class Application {
abstract public void execute(ArrayList<String> args, OutputStream outputStream, InputStream inputStream) throws IOException;
}
And I will call the concrete class that extends Application by
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Application app = (Application)context.getBean(appName);
My questions are:
Is it a bad practice to initialise a bean without any field (or all the fields are constants) using Spring?
As there is no dependency to other classes in Application, are we still consider this as a dependency injection or IOC? If no, what is the difference between this and a normal factory pattern? It seems that what Spring does here is simply matching the class and initializing it.
UPDATE
Here is the code snippet of the class where the instance of Application is needed.
String appName = argument.get(0);
Application app = ApplicationFactory.getApplication(appName);
ArrayList<String> appArgs
= new ArrayList<String>(argument.subList(1, argument.size()));
app.execute(appArgs, outputStream, inputStream);
Further questions:
in my code the class X will call the instance of Application by specifying a concrete application class name. In this case, it is still not possible for Spring to inject the dependency to Application, right? As what I need is a concrete class but not Application itself.
if Application does have fields but these fields are initialsed somewhere higher than X (X receives them as inputs and passes them to Application), can I use DI in this case?
Is it a bad practice to initialise a bean without any field (or all the fields are constants) using Spring?
No, its totally fine. Its true that you won't be able to "take advantage" of the automatic dependency injection mechanisms provided by spring (because obviously there are no dependencies in the class Application in your example), however spring can still:
Make sure that the Application as a singleton "obeys" the rule of being a single instance in the whole application context. For "manually" maintaining singletons you need to write code. Spring does it for you.
Manages the lifecycle of the object. Example, Spring has "postConstruct"/"preDestroy" methods that can can be run in the appropriate time and make example any custom code of the class Application.
If this class does some heavy-lifting (even without spring) than it can make sense to define it "lazy" so that the initialization of this instance will actually be done upon the first request to it.
Sometimes you/or spring itself will create a proxy of this class in runtime (for many different reasons, for example this aforementioned lazy functionality, but there are also other use cases). This is something that spring can do for you only if it manages the Application and not if its defined outside the spring.
Ok, you don't have dependencies in the application, This means that this Application class has some useful methods (at least on method, like public void foo() for
simplicity). But this in turn means that there is some class (lets call it X) that calls this method. So this class has an instance of Application as a dependency. So now the real question is who manages this class X. Probably it makes sense to manage it in Spring as well, and then you will benefit of the Dependency Injection mechanisms in this class X only because Application is also managed by Spring. In general Spring can inject dependencies only if these dependencies are managed by Spring.
I know, this last paragraph may sound vague given the use case you've presented, but you've got a point, for example in real application people make an initial bootstrapping in very certain places. Usually also people use spring boot that kind of encapsulates this kind of things for you.
As there is no dependency to other classes in Application, are we still consider this as a dependency injection or IOC? If no, what is the difference between this and a normal factory pattern? It seems that what Spring does here is simply matching the class and initializing it.
So as you see, the concept of DI container goes far beyond of what the factory pattern has to offer. In short, factory pattern only specifies the way to create the objects. Spring on the other hand, not only creates the objects but also manages them.
First, I very strongly suggest that you use Spring Boot instead of manually manipulating Spring at a low level like this.
It's perfectly ordinary to use beans that don't have their own fields for settings, but this is usually so that other beans can have pluggable strategies or providers and you can define in your application setup which to use.
If your Application class doesn't need anything else, then there really is not much advantage to Spring. Most real-world programs get complicated soon, however, and that's where it becomes useful.
Finally, you should almost never pass ArrayList as a parameter; use List instead. In the code you showed, however, if you have String[] args, you couldn't say app.execute(Arrays.asList(args), System.out).

How to inject fields in bean-methods?

Sonar-linter think that right way to inject is:
#Bean
public Example example(DataSource datasource) {
return new Example(datasource)
}
but if only one method's using this field. I'm curious, why exactly one method? And maybe better do #Autowired?
Quote from Sonar's rule:
When #Autowired is used, dependencies need to be resolved when the class is instantiated, which may cause early initialization of beans or lead the context to look in places it shouldn't to find the bean. To avoid this tricky issue and optimize the way the context loads, dependencies should be requested as late as possible. That means using parameter injection instead of field injection for dependencies that are only used in a single #Bean method
As your Quote says, #Autowired needs the dependency to be resolved when the class is Initialzed. Parameter Injection instantiates the bean only when it‘s needed. This increases the effectivity of your Code.
The reason for the Single Method is caused by lifecycle of a Bean. By default Beans are singletons which means they are Shared like static Objects. So if multiple Objects will use the bean it is more effective to inject them with autowired because the possibility That it will be used is much higher and so you provide the Shared instance at Startup

Injection of Multiple Conflicting Dependencies in Spring

I have a Spring bean class which requests dependencies to be injected. However, in my class, I am manually wiring different dependencies to the same private class variable. What happens in this scenario? Which injection takes precedent?
Details:
I have created a Spring bean class called BadmintonCoach.
It relies on an IfortuneService helper. IfortuneService is an interface with TWO different implementations. The two implementations are:
FortuneService_RESTful
FortuneService_Random
In my badmintonCoach class, I have created a private variable to receive the injection from Spring:
private IFortuneService theFortuneService
That is to say, I am manually wiring up the the injected dependency to this private member, theFortuneService
I am injecting these iFortuneService dependencies using method injection.
BUT here is the problem: I have TWO methods, both of which request an injection from Spring of the type iFortuneService. One method requests one implementation (FortuneService_RESTful) and the other method requests a bean of the other implementation (FortuneService_Random).
Both of these methods set this.theFortuneService equal to its respective requested helper. So what I have within my BadmintonCoach class is:
private IFortuneService theFortuneService
#Autowired
#Qualifier("fortuneService_Random")
public void randomMethod_ONE(IFortuneService theFortuneService) {
System.out.println("Code inside randomMethod_ONE!");
this.theFortuneService = theFortuneService;
}
#Autowired
#Qualifier("fortuneService_RESTful")
public void randomMethod_TWO(IFortuneService theFortuneService) {
System.out.println("Code inside randomMethod_TWO!");
this.theFortuneService = theFortuneService;
}
My question then, is:
Which of the two wirings wins out? Why? How does Spring decide the ORDER of its injections? What determines the order of the injections? Is it random? Is it injected in alphabetic order of the method names? Is there an order of injection between constructor, setter, field and method injections?
What am I seeing when I run my program? I am seeing the injection of fortuneService_RESTful win out, but it is unclear to me whether this is by chance or by design from within Spring's logic.
Here is another thought:
What if, instead of requesting different implementations of the IFortuneService interface, the two methods above asked for the same bean but that bean was prototyped? Clearly, there would be a new incarnation created for each request and there would only be one helper class assigned to my BadmintonCoach class. But which incarnation would win out?
I can provide the whole of my code if it will make my question clearer.
If you are wondering WHY I have written conflicting code? It is plain and simple curiosity to try and understand how Spring works behind the scenes.
OK folks, it has taken a day for me to see this but I can confirm that what happens here is indeed random!
Yesterday, I was exclusively seeing method_ONE win out. Today, I am seeing method_TWO win out. I can therefore conclude that the order of injections by Spring is indeed random!
Thomas Klager had provided a suggestion in the comments above which may explain this phenomenon:
One obvious reason [for this] is that using annotation based injections, spring
needs to list the methods of a class using Class.getDeclaredMethods()
or Class.getMethods(). Neither of these methods return the methods in
any particular order.
I still find it a mystery how execution of the same logic by Spring (ie: Class.getDeclaredMethods() or Class.getMethods()) can yield random results like this.
It is very important to be aware of this limitation! When writing code, you may find yourself wanting to use the services of injected dependencies which in turn depend on the services other injected dependencies. It is clear from this experiment that this could potentially be dangerous and therefore you should not layer your wiring in this manner. That is to say, your wiring should always be single tiered if it spans multiple methods, otherwise, you risk spurious output from your program. An illustration of this danger can be seen in Slim's answer in this link.

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.

Spring dependency injection for multiple classes

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/

Categories