I saw this question
Inject into private, package or public field or provide a setter?
about how to manually inject into annotated private fields (The way is adding setters or through a constructor)
But, the point is how do an application server (like glassfish, axis2, jboss, ...) is able to inject into a final private field (without adding setters or constructors to the user class)?
Quoting the cited question:
public SomeClass {
@Inject
private SomeResource resource;
}
Do they use a customized JVM (not the standard one) that allows to access private fields?
Thanks
Dependency Injection (DI) is a design pattern used to implement IoC. It allows the creation of dependent objects outside of a class and provides those objects to a class through different ways. Using DI, we move the creation and binding of the dependent objects outside of the class that depends on them.
There are three types of dependency injection — constructor injection, method injection, and property injection.
Dependency injection enables you to turn regular Java classes into managed objects and to inject them into any other managed object. Using dependency injection, your code can declare dependencies on any managed object.
Injectable constructors are annotated with @Inject and accept zero or more dependencies as arguments. @Inject can apply to at most one constructor per class. @Inject is optional for public, no-argument constructors when no other constructors are present. This enables injectors to invoke default constructors.
It's a simple reflection "trick". It relies on the Field.setAccessible()
method to force the member to be accessible programmatically:
Set the accessible flag for this object to the indicated boolean value. A value of true indicates that the reflected object should suppress Java language access checking when it is used. A value of false indicates that the reflected object should enforce Java language access checks.
The Reflection API is used to get a handle on the field, setAccessible()
is called, and then it can be set by the injection framework.
See an example here.
No magic, no custom VM.
With the help of skaffman I coded this simple example on how to inject without setters. Perhaps it helps (It did to me)
//......................................................
import java.lang.annotation.*;
import java.lang.reflect.*;
//......................................................
@Target(value = {ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@interface Inject {
}
//......................................................
class MyClass {
@Inject
private int theValue = 0;
public int getTheValue() {
return theValue;
}
} // class
//......................................................
public class Example {
//......................................................
private static void doTheInjection(MyClass u, int value) throws IllegalAccessException {
Field[] camps = u.getClass().getDeclaredFields();
System.out.println("------- fields : --------");
for (Field f : camps) {
System.out.println(" -> " + f.toString());
Annotation an = f.getAnnotation(Inject.class);
if (an != null) {
System.out.println(" found annotation: " + an.toString());
System.out.println(" injecting !");
f.setAccessible(true);
f.set(u, value);
f.setAccessible(false);
}
}
} // ()
//......................................................
public static void main(String[] args) throws Exception {
MyClass u = new MyClass();
doTheInjection(u, 23);
System.out.println(u.getTheValue());
} // main ()
} // class
Run output:
------- fields : --------
-> private int MyClass.theValue
found annotation: @Inject()
injecting !
23
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With