I have a class SomeClass and a SomeModule to register it with Guice.
I found out that the constructor SomeClass is only called by SomeModule, and that SomeModule is the only place where binding for SomeClass happens.
This means that the #Inject on SomeClass's constructor is not needed since prop1 and prop2 are injected inside SomeModule and passed to the constructor. And the testing also seems to prove my findings.
My question is that what Guice will do when it sees a #Inject like this?
Also what side effect will there be if I have an excessive #Inject?
public static class SomeModule extends PrivateModule {
#Provides
#Singleton
#Exposed
private SomeClass someClass( SomeObject prop1, String prop2) {
return new SomeClass(prop1, prop2);
}
}
public class SomeClass {
#Inject // unnecessary
public SomeClass(SomeObject prop1, String prop2){
...
}
}
If my understanding is correct, you #Inject a constructor when you want to inject objects managed by Guice into the parameters of the constructor.
e.g. if I have bind(SomeClass.class).in(Singleton.class) and bindings for prop1 and prop2, it makes sense to #Inject SomeClass constructor in order to inject prop1 and prop2 into the constructor.
But since this isn't the case, this makes the #Inject here unnecessary
Cheers
Quoting #Deepak's comment as the answer:
You need #Inject if you were defining a binding in the configure method instead of creating a Provider for this class. When you define a binding in the configure method, you are telling Guice to instantiate the object for you. That is when it looks for a constructor with #Inject to figure out what dependencies it has to Inject to construct that object. In case of Provider, you are creating the object yourself by passing all the dependencies required for that class as arguments. So, #Inject has no meaning at that case
Related
I've got a parent class with a constructor injected dependency:
class ParentClass {
private final MyService service;
#Autowired
ParentClass(MyService service) {
this.service=service;
}
// ...
}
If I inherit from this class, do I always need to redefine a constructor calling the parent constructor?
class ChildClass extends ParentClass {
// Do I really need this?
#Autowired
ChildClass(MyService service) {
super(service);
}
// ...
}
Using setter injection, I seem to be able to keep the dependency in the parent class and do not need to rewire it in the child, which sounds good to me if the child class does not touch the functionality linked to the dependency:
class ParentClass {
private MyService service;
#Autowired
void setMyService(MyService service) {
this.service=service;
}
// ...
}
class ChildClass extends ParentClass {
// ...
}
It seems that if I want to avoid repeating the autowiring code and handling the dependency in the child, I can only do this using setter or field injection.
Is there a cleaner pattern to do this dependency injection or is this a case where field/setter injection has to be used, even though constructor injection is recommended?
Thanks!
It's not a Spring issue, it's Java. Try removing child class constructor, and see what happens for yourself - your code shouldn't compile. See this answer, it was described before.
Answering your question on dependency injection, yes, #Autowired works for setter in the parent class, but as long as you don't override it in the subclass (give it a try). The reason is that Spring deals with objects, not classes, so when a subclass is instantiated Spring is not checking annotations on overridden methods in the parent class, unless annotation is marked as #Inherited (#Autowired is not).
So, you would either have to use #Autowired for each subclass (which I don't see as a big problem, actually), switch to setter injection, replace subclassing with delegation, or make parent class abstract and use constructor injection only in subclasses.
I have a class with overloaded constructors, like this:
#Component
public class MyClass {
private ClassA myMemberA;
private ClassA myMemberB;
#Autowire
public MyClass(#Qualifier ("qualifierA") ClassA objectA, ClassA objectB) {
myMemberA = objectA;
myMemberB = objectB;
}
#Autowire
public MyClass(ClassA objectA) {
myMemberA = objectA;
}
}
Basically, one constructor has two arguments of ClassA, and one constructor has just one argument. I have two beans of type ClassA defined.
I would like to have one of the two constructors invoked and autowired accordingly depending on the use case.
When I ran this code, I got the error:
Invalid autowire-marked constructor: ...
Found another constructor with 'required' Autowired annotation: ...
Is it possible to have overloaded autowired constructors? If yes, what is the right way to do it?
Thank you!
You need to define which constructor Spring will be prioritizing by writing something like this: #Autowired(required=true) or #Autowired(required=false). You are only allowed to have one constructor with #Autowired(required=true). By default, if you don't define the required property, it will be set to true, which is the problem in your case.
I don't see the point of having two Autowired constructors if only one of them will be wired anyway. If you're trying to Autowire the two instances of ClassA, it might be better to add the #Autowired annotation to the setters or the variables.
I got a class like the following:
public class MyClass {
#Inject
private SomeClass someclass;
//...
}
If I create this class by new MyClass() then someClass is null. If I inject MyClass it is not. But I need the construction with new here. I know I could pass someClass to MyClass via constructor, but I don't want this. What other possibilities do I have here?
I assume you're using CDI or something similar. For injection to work in that case the framework has to "see" the need to inject something (and where to inject that). That's generally done by creating MyClass instances by using the framework as well but there might also be a way to trigger injection manually.
In terms of CDI it would be something like this:
BeanManager bm = ...; //lookup or let it inject
Bean<MyClass> bean = (Bean<MyClass>)bm.getBeans( MyClass.class ).iterator().next();
CreationalContext<T> ctx= bm.createCreationalContext( bean );
MyClass instance = bm.getReference( bean, MyClass.class, ctx);
I found a pretty nice solution. The trick is to inject ´MyClass´ in the following way:
#Inject
private Instance<MyClass> myClass;
Then you can construct the bean via
myClass.get();
This encapsulates the usage of the beanManager.
Suppose you have one interface
public interface A {
public void doSomething();
}
and two implementation classes
#Component(value="aImpl1")
public class AImpl1 implements A {
}
#Component(value="aImpl2")
public class AImpl2 implements A{
}
And finally a class that will use an "A" implementation:
#Component
public class MyClass {
#Autowire
A a;
}
Now if I want to inject AImpl1 I add the #Qualifier("aImpl1") while if I want to inject AImpl2 I add #Qualifier("aImpl2")
The question is: Is it possible to instruct spring somehow to look up all implementations of "A" in this case AImpl1 and AImpl2 and use some application specific conventions to choose the most appropriate implementation? for example in this case my convention could be use the implementation with the greatest suffix (i.e. AImpl2)?
EDIT: the class MyClass should not be aware at all about the implementation lookup logic, it should just find its property "a" set with an object of AImpl2.
You can inject all implentations as List:
#Autowired
List<A> as;
or as Map with bean name as key:
#Autowired
Map<String, A> as;
and then choose proper implementation manually (perhaps, in a setter method):
#Autowired
public void setAs(Map<String, A> as) {
this.a = ...;
}
Assuming you already have hundreds of interfaces and implementations (as you said in a comment), and you do not want to refactor all the code... then is a tricky problem... and this is a tricky solution:
You could create a custom BeanDefinitionRegistryPostProcessor and implement either the method postProcessBeanDefinitionRegistry or postProcessBeanFactory.
This way you have access to all bean definitions before they are instantiated and injected. Do your logic to find which is the preferred implementation for each one of your interfaces, and then, set that one as primary.
#Component
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
#Override
public void postProcessBeanDefinitionRegistry(
BeanDefinitionRegistry registry) throws BeansException {
// this method can be used to set a primary bean, although
// beans defined in a #Configuration class will not be avalable here.
}
#Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
// here, all beans are available including those defined by #configuration, #component, xml, etc.
// do some magic to somehow find which is the preferred bean name for each interface
// you have access to all bean-definition names with: beanFactory.getBeanDefinitionNames()
String beanName = "aImpl2"; // let's say is this one
// get the definition for that bean and set it as primary
beanFactory.getBeanDefinition(beanName).setPrimary(true)
}
}
The hard part is to find the bean name, it depends of the specifics of your application. I guess that having a consistent naming convention will help.
Update:
It seems that both methods in the interface BeanDefinitionRegistryPostProcessor can be used for this purpose. Having in mind that in the postProcessBeanDefinitionRegistry phase, beans configured through #configuration classes are not yet available, as noted in the comments below.
On the other hand they are indeed available in postProcessBeanFactory.
If you have a Configuration class you could use a method in that to make the decision of which implementation of A to return. Then the autowired will inject the appropriate instance for that class.
#Configuration
public class ApplicationConfiguration {
#Bean
A getA() {
// instantiate the implementation of A that you would like to have injected
// or you could use reflection to find the correct class from the classpath.
// return the instance
}
}
This assumes you always want to use the same instance everywhere you are injecting A. If not, then you could have different #Bean annotated methods with names to get different versions.
You can try to use Spring Profiles.
I am using an library which internally has a class
#ImplementedBy(MyClassImpl.class)
public interface MyClassInterface {
....
}
When Guice, how can get the instance of the MyClassImpl?
Do I have to create a binding:
bind(MyClassInterface.class).to(MyClassImpl.class);
in order to use it?
Many thanks
No, you don't have to create a binding, although you can. If you do it will override the #ImplementedBy annotation.
You can get an instance of it via ordinary injection, e.g.
#Inject
public Client(MyClassInterface foo) {
...
}
or (if it's the top-level class):
injector.getInstance(MyClassInterface.class);
You either inject the interface:
#Inject
MyClassInterface myClass;
or you can use an injector to get an instance:
MyClassInterface myClass = injector.getInstance(MyClassInterface.class);
both will be injected with the MyClassImpl type.