Independently of the DI Framework used - a single POJO within the object chain always breaks the DI mechanism.
Pseudocode example:
class A {
#Inject
private B b;
}
class B {
private C c=new C();
}
class C {
#Inject
private D d;
}
The injection in class C won't work, as the new C() in class B breaks the chain of managed objects.
We are currently trying to improve our old (non-DI) project by incrementally replacing manual object creation with DI mechanisms.
So how to migrate C to DI, without even caring about A and B?
You can not do that with keeping the direct calls to the constructor (without bytecode manipulation).
Here is a way to semi-automatically refactor your code to what you might need.
The usual IDE lets you create/refactory factory methods out of constructors. With doing that refactoring all calls to new C() will be transformed to C.createInstance() (or whatever the factory method is called).
Afterwards change the factory method to actually resolve the C from your dependency injection framework.
Normally if you don't want to inject the C you call your container to resolve C:
C c = container.resolve(C.class);
or you let the C also be injected e.g. when calling the constructor
or like you did before:
#Inject
private C c;
Here are is some example code for CDI:
https://jaxenter.de/cdi-geht-fremd-dependency-injection-fur-javase-5039
The resolve the needed object by using:
UpdateCustomerController controller = (Controller) BeanProvider.getContextualReference("updateController", false);
Related
I have java classes like this :
#Data
public class Lead {
private A a;
...
}
#Data
public class A {
private B b;
private String c;
private List<Integer> d;
}
#Data
public class B {
private String e;
private String f;
}
I have a mapper method with annotation like this :
#FieldPermissionAnnotation("a")
public A fetchA(//Some DB Entities) {
A a = new A();
...
a.setB(fetchB());
...
a.setC(fetchC());
...
a.setD(fetchD());
}
My FieldPermissionAspect fetches the permission-field mapping from db for a user and sets field to null if user does not have permission for given field.
I get a list of string field hierarchy like this :
["a-b-e", "a-b-f", "a-c", "a-d"]
I want to set b, c, d to null using #Around around their respective setters inside the fetchA() method.
Is it feasible using AspectJ and spring?
How do I access the setters for b, c, d inside the fetchA() method?
I want to set b, c, d to null using #Around around their respective setters inside the fetchA() method. Is it feasible using AspectJ and spring? How do I access the setters for b, c, d inside the fetchA() method?
As I said in my comment, your question is unclear and I have to guess what you want to do because there is no aspect code. My assumption is that you want to intercept setter methods if (and only if) they are being called from inside a certain other method. I.e. you need a control-flow-dependent pointcut like cflow() or cflowbelow(). According to the Spring manual these pointcuts are not supported by Spring AOP, but you can configure Spring to use full AspectJ with LTW (load-time weaving) instead.
For more details I suggest you show me yours (MCVE, ideally on GitHub with Maven build), then I show you mine (concrete solution).
When programming with Magento (PHP), I practiced DI when overriding classes. I can freely add any parameters in any order as I wish in the constructor functions to inject service dependencies, something as below:
class X
{
protected $service_a = null;
protected $service_b = null;
...
public function __construct(ServiceA $a, ServiceB $b, ... )
{
$this->service_a = $a;
$this->service_b = $b;
...
}
}
Somehow, in somewhere, when class X is instantiated, the system could automatically detect the parameter definition in the constructor of class X. Does not matter how do I modify the definition, the system always pass the correct services to the constructor. In Angular, the same story.
My question is how to make it possible in PHP and javascript??? If I define my own class, I have to instantiate it according to the constructor definition. How do they make the process (detect the parameter in constructor) done automatically?
I want to conduct a chain of processing elements and wire them together via Guice. Let's assume the following path:
interface A implemented by class AImpl needs some input
interface B implemented by class BImpl needs A
interface C implemented by class CImpl needs B
interface D implemented by class DImpl needs C
The dependency of A can only be resolved at runtime and not at configuration time. The usual approach would be to use Assisted Injection in this case to create a factory, that takes the missing instances as parameters, just like this:
public interface AFactory {
public A createA(String input);
}
But what I actually want is something like this:
public interface DFactory {
public D createD(String inputForA);
}
I don't want to manually pass AImpl-specific dependencies through the whole hierarchy.
Is it possible to achieve this with Guice? If not, what's the best way to circumvent this problem elegantly while still retaining benefits of injection?
Cheating way: Stick input in a static variable or singleton ThreadLocal. Set it before your pipeline starts and clear it after it ends. Bind everything else through DI.
Fancy way: In A, refer to a #PipelineInput String inputString but don't bind it in your main injector. Otherwise, bind dependencies as you normally would, including referring to #PipelineInput in other pipeline-related classes. When you do need a D, get it from your implementation of a DFactory, which I'm calling PipelineRunner.
public class PipelineRunner {
#Inject Injector injector; // rarely a good idea, but necessary here
public D createD(final String inputForA) {
Module module = new AbstractModule() {
#Override public void configure() {
bindConstant(inputForA).annotatedWith(PipelineInput.class);
}
};
return injector.createChildInjector(new PipelineModule(), module)
.getInstance(D.class);
}
}
Naturally, binding attempts for A, B, C, and D will fail outside of PipelineRunner for lack of a #PipelineInput String--you'll get a CreationException when you create the injector with those unsatisfied dependencies, as you discovered--but those pipeline-based dependencies should be easy to separate into a Module that you install into the child injector.
If this feels too hacky, remember that PrivateModules are also "implemented using parent injectors", and that the whole point of dependency injection is to make a dependency like inputForA available to the whole object graph in a decoupled way.
I see three options. They depend on how often you change the input for A .
1) Bind input as a constant in your module. This works only, if you know that value before you create the Injector and never want to change the value. See bindConstant
2) Use a private submodule which binds either A or the value for input inside that module. Basically you can have two or three instance graphs with different value. See newPrivateBinder.
3) Use a Scope ala RequestScope, SessionScope, ... This way you can change the input often but you must enter/leave the scope at some point to be defined. See Custom Scopes for an example.
I have a general understanding problem with dependency injection, independent of a specific dependency injection framework. Let's say I have a class which needs a runtime parameter:
class ClassWithRuntimeDependency {
ClassWithRuntimeDependency (String myRuntimeParameter) {
//...
}
}
Now to get this runtime parameter into my class, documentations of several dependency injection frameworks tell me to use a factory. This factory takes the runtime parameter and creates an instance of ClassWithRunetimeDependency with it.
But let's say this ClassWithRuntimeDependency is kind of a very basic class which is needed by nearly all other classes:
Class A -> Class B -> Class C -> Factory<ClassWithRuntimeDependency>.
Now I cannot create class C without this runtime dependency either, so I need to make a factory for it. But the same applies to classes A and B! This leads to a factory for class A with a runtime dependency which is only needed for constructing ClassWithRuntimeDependency. This means I do not inject a direct dependency into class A, which isn't best practice either (github). Instead of using factories everywhere, I know I could also introduce this runtime dependency to all needed methods, but this only shifts the problem.
Do I have a misunderstanding here or is there any better solution to this?
To further express the problem, this could be my classes A-C if I would have used factories everywhere:
// Needs a factory because of runtime parameter.
// Imho, this is the only class which should really need a factory because
// it is the only class having the direct runtime dependency, all
// others below are indirect
class ClassWithRuntimeDependency {
ClassWithRuntimeDependency (String myRuntimeParameter) {
//...
}
}
// Needs a factory because of runtime parameter in ClassWithRuntimeDependendcy
class C {
C(String myRuntimeParameter, #inject FactoryForClassWithRuntimeDependency reallyNeededFactory) {
this.withRuntimeDependency = reallyNeededFactory(myRuntimeParameter);
}
}
// Needs a factory because of runtime parameter in C -> ClassWithRuntimeDependendcy
class B {
B(String myRuntimeParameter, #inject FactoryForC cFactory) {
this.c = cFactory(myRuntimeParameter);
}
}
// Needs a factory because of runtime parameter in B -> C -> ClassWithRuntimeDependendcy
class A {
A(String myRuntimeParameter, #inject FactoryForB bFactory) {
this.b = bFactory(myRuntimeParameter);
}
}
(I did not use the syntax of a specific DI framework)
So I end up having an AFactory with a dependency that is only needed by ClassWithRuntimeDependency. Of course, I could also leave out the parameter in the constructor and use it methods only (as suggested here), but if I have in any of these classes many methods which needs this parameter, this really blows up my API in all dependent classes, therefore kind of only shifts the problem.
The only solution I came up so far is to inject a context object (or a provider of a context object), and fill this context object with runtime data. But this also leads to temporal coupling and makes it harder to test.
This is why you should have Inversion of Control container and allow him to do dirty work for you. Like Spring does. You just point what kind of dependency you need for your bean through configuration and Spring inject this dependency.
I was kind of lazy and used to use almost entirely field injections. I was just providing empty constructor, put my #Inject fields I everything was looking nice and simple. However field injection have its trade-offs so I've devised some simple rules that help me to decide when to used field and when to use constructor injections. I will appreciate any feedback if there is mistake in my logic or if you have additional considerations to add.
First some clarification in order to be on the same page:
Constructor injection:
#Inject
public SomeClass(#Named("app version") String appVersion,
AppPrefs appPrefs) {...
Same with the field injection:
public class SomeClass {
#Inject
#Named("app version") String mAppVersion;
#Inject
AppPrefs appPrefs;
Rule 1: MUST use field injection if I don't control creation of the object (think Activity or Fragment in Android). If some (non-dagger aware) framework is creating my object and handles it to me I have no choice but to inject it manually after I receive the instance.
Rule 2: MUST use constructor injection if the class is/may be used in another project that does not use Dagger 2. If the other project(s) do not use Dagger they cannot use DI so the user have to create the object the "old" way using new.
Rule 3: PREFER constructor injection when working with class hierarchies because it is easier to create unit tests.
Clarification:
Considering the following structure that uses field injection:
package superclass;
public class SuperClass {
#Inject
HttpClient mHttpClient;
...
}
.
package differentpackage;
public class SubClass extends SuperClass {
public SubClass() {
}
}
When I am creating unit test for SubClass in directory test/java/differentpackage I have no choice but to bring up the entire DI infrastructure in order to be able to inject the HttpClient. In contrast, if I was using constructor injection like this:
public class SuperClass {
private final HttpClient mHttpClient;
#Inject
public SuperClass(HttpClient httpClient) {
mHttpClient = httpClient;
}
}
in my unit test I could simply:
HttpClient mockHttp = mock(HttpClient.class);
Subclass tested = new Subclass(mockHttp);
// tests
So basically now I am in the other extreme: I tend to rely mostly on constructor injections and use field injections only when 'Rule 1' applies.
The only 'problem' that I have with the constructor injects is that for 'end' classes constructors sometimes become quite overloaded with parameters and they look verbose and ugly like this:
#Inject
public ModelMainImpl(#Named("app version") String appVersion,
AppPrefs appPrefs,
LoginPrefs loginPrefs,
#ForApplication Context appContext,
NetworkInfoProvider networkInfoProvider,
AndroidEventPoster androidEventPoster,
Session session,
ForgeExchangeManager exchangeManager,
HttpFunctionality httpFunctionality,
#Named("base url") String baseUrl,
#Named("forge result producer") ResultProducer<ForgeExchangeResult> resultProducer
) {
Guys, what are your rules to choose between constructor and field injects? I am missing something, are there errors in my logic?
Use constructor injection. if you can't, use property injection.
Rule 1 seems ok, like decorations or attributes you can use Property(field) injection.
Rule 2 seems ok, because who uses your class they have to follow your constructor. They may not know they have to intilaize your property also.
Rule 3 It's not just good for unit test. It's good for applying Single Responsibilty. It's easier to see your object graph.Otherwise you will hide it with property.
If we come in your question, yes there a lot of parameters in your constructor. But the solution is not property injection. You can refactor your code and use aggregate services