Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing "containing class" from DependencyDescriptor

I'm working on a utility for supporting context-dependent injection, i.e. what gets injected can now also depend on where it is injected. Logger injection is a common application of this technique. So far, I've successfully implemented this for HK2 and Guice, and with some limitations for Dagger. To solve this for Spring, I'm using a BeanFactoryPostProcessor that registers an AutowireCandidateResolver. However, to achieve the intended semantics, I need to know the type of the actual target object, which may be different from the type that declares the injection point. For example:

class BaseClass {
    @Inject Logger logger;
}

class SubClass extends BaseClass {
}

Instances of SubClass need to be injected with a logger for SubClass, not with a logger for BaseClass. The DependencyDescriptor contains this information in the containingClass field, but unfortunately this information is not exposed via the API.

Question 1: Is there an architectural reason that this information is not exposed, or could a getter for this be added to the DependencyDescriptor API?

Question 2: In the meantime, what is the best way to work around this limitation? Accessing the internal field via the Reflection API is ugly and violates encapsulation. The other alternative is to inject the wrong (i.e. Logger for BaseClass) instance first and then later correct it with a BeanPostProcessor, but I would be manually redoing a lot of work (i.e., reprocessing pretty much the entire injection handling).

like image 898
raner Avatar asked Nov 10 '15 19:11

raner


1 Answers

Now quite sure what is the reason of the strictness of DependencyDescriptor API. But the starting point for you should not be the BeanFactoryPostProcessor but you should have a look at BeanPostProcessor and particularly at AutowiredAnnotationBeanPostProcessor which autowires annotated fields, setter methods and arbitrary config methods based on the @Autowired, @Value and @Inject annotations. As I understand this is what you want to do. This class is the responsible for creating DependencyDescriptor. So may be what you need to do is:

  1. Create a custom DependencyDescriptor (just extend it with public access to "containing class")
  2. Create a custom AutowiredAnnotationBeanPostProcessor which will do same things as AutowiredAnnotationBeanPostProcessor but instead of creating the instance of DependencyDescriptor will create the one from step 1.
  3. Create a custom AutowireCandidateResolver which will just cast the DependencyDescriptor to the one which you have created (so can publicly access "containing class" property.)
like image 102
Babl Avatar answered Oct 13 '22 13:10

Babl