Run method each time a specific annotation is used in a class - java

Say I have a class with a few fields all marked with a custom annotation. In my case it is #inject, because this is being used for dependency injection. How can I run a method in a separate class each time that annotation is used in my a class? In other words, each time a class is loaded the annotation runs a method that will collect the field data and in turn set the field.
I already have the entire system set up for collecting the resources, but I need some direction on how to actually run that code when the class with #inject annotation is loaded. Is this something that can be done by defining some sort of method in the annotation interface that performs the data collection?
My initial thought is to use a custom class loader, but I don't want to have to set the class loader when I use this jar in other projects. Is there a way to set a custom class loader programmatically for specific classes at runtime? I'm already doing a lot of pre-runtime reflection stuff and i'll already know which classes need to be loaded with a custom loader. Its just a matter of not knowing or if its even possible to set a custom loader on a class from within the code.
Can a classloader even be used to perform tasks such as pre-populating fields, or am I running off on a wrong tangent here? I just need a little direction on the most common way this type of thing is done (pre-populating class fields at runtime).

I was overthinking this problem. You cannot actually run code automatically prior to loading a class (unless its a servlet filter etc). In my situation the answer was to create an instance based on a specific class that already held the resource data I needed. Similar to how Google's Guice does it.
See this question for more insight: How does Guice Populate Annotated Fields

You can use injectors from Google Guice or Spring Framework.

Related

reset static field to their initial value using reflexion in java

I use in my project a lib with some class with a lot of static field and other stuffs, who are indirectly updated and consulted at runtime in my app.
I can't update or ignore or mock this class.
How can I re-execute the method who initialise the static field of a class?
I'm currently writing test in my app, which trigger this class.
I want the static field of this class to be at their init state each time I start my app.
The issue is, setting manualy those static field is not possible, it would be too complexe. I need them to be put at their initial state "automaticaly"
I can't change anything to the code of the class, because it's in a lib.
Any idea how I can do that? With reflexion, maybe?
If resetting static fields manually are too complex and classes are stateless, one of the way could be to use custom class loader and reload your classes whenever required.
This article may provide some idea about loading and reloading classes.
You should watch out for performance hit.

Extend a Java Class and force existing libraries to use the extended class

The situation is as follows: I'm using some libraries that use a specific class to load and access configuration parameters. The config loader class is implemented in one of the libraries.
What I did is: to extend the config loader class so that it fits my requirements and is able to load different config sources:
public class BetterConfigLoader extends OldConfigLoader {
...
}
Now I want to make the existing libraries use my compatible BetterConfigLoader without applying changes to the libraries or without the need to recompile them.
Is there a way of best practice to accomplish this?
This depends on how your libraries refer to the configuration class. Do they have a hardcoded new OldConfigLoader().configure()?
Or do they use some kind of SPI technique, e.g. checking for existence of a resource named META-INF/services/ConfigLoader, and only if not existing, falling back to the default configuration class?
Instead of checking such a resource, they could as well check a System Property.
In these cases, you can set your special class by creating a matching SPI resource, or by setting the System Property.
In case of hardcoded reference, you are out of luck.
Instead of extending OldConfigLoader you can replace it. Start with the source code of OldConfigLoader, change it to suit your needs and then make sure your version is higher in the classpath then the original. Make sure your implementation has the same classname and is in the same package as the original.

How can I inject a named component into a sub-graph in Dagger 2?

so I'm working on a project using Dagger 2 in Android. I have two objects that are scoped #Singletons of the same type, so I've used the #Named("some name") annotation to distinguish the two, But I'm trying to expose these two objects to the sub-graphs, such as #PerActivity, but am not able to think of a simple way of doing that. usually when I want to expose a sub component it's easy... just add it to my ApplicationComponent interface, but in this case I don't know how to do that sense both components are of the same type. Is there a clean way of doing this? or am I going about it wrong? any help with this would be greatly appreciated.
You can use the #Named("some name") annotation in both your modules and your components. Which means that if you specify the two provision methods with different names but the same return type with the added annotation, you should be able to expose both to the subgraph.
You are correct by using #Named("NAME_GOES_HERE") to have 2 singletons of the same type.
class ExpensiveCoffeeMaker {
#Inject #Named("water") Heater waterHeater;
#Inject #Named("hot plate") Heater hotPlateHeater;
...
}
Source: http://google.github.io/dagger/
Be sure that when you are injecting these things you include the #Named("YOUR_NAME_GOES_HERE") annotation as well.
I haven't used the #PerActivity annotation that you mentioned; I've only used a single graph in my projects. Why do you need an injection per activity anyways? Can't you just maintain state within that activity and use the injected dagger component globally with the local state data you are keep within the activity?

Dependency Injection With Annotations

I would like to build my own custom DI framework based on Java annotations and I need a little direction to get started. I know it would be much easier to use one of the many wonderful frameworks out there such as guice or spring, but for the sake of my own curiosity, i'd like to build my own.
I'm not very familiar with annotations, so i'm having a bit of trouble finding resources and would really appreciate someone just sort of spelling out a few of the steps i'll need to take to get started.
As fore mentioned, id like to take a factory approach and somehow label my getters with an #Resource or #Injectable type annotation, and then in my business classes be able to set my variable dependencies with an #Inject annotation and have the resource automatically available.
Does anyone have any sort of resource they can pass along to help me understand the process of tagging methods based on annotations and then retrieving values from a separate class based on an annotation. A little direction is all I need, something to get me started. And of course i'll be happy to post a little code sample here once I get going, for the sake of others future reading of course.
EDIT
The resources I am using to put this together:
Java Reflection: Annotations
How to find annotations in a given package: Stack Overflow ?
Scanning Annotations at Runtime
I have not actually finished writing this yet, but the basic task list is going to be as follows (for anyone who might be interested in doing something similar in the future)
At class runtime scan for all #Inject fields and get object type.
Scan all classes (or just a specific package of classes (I haven't
decided yet)) for annotated methods #InjectableResource.
Loop all annotated methods and find the method that returns the
object type I am looking for.
Run the method and get the dependency.
It will also be helpful to note that when scanning all the classes I will be using a library called Javassist. Basically what this does is allows me to read the bytecode information of each class without actually loading the class. So I can read the annotation strings without creating serious memory problems.
Interesting that you want to build your own. I love Google Guice - it makes code so elegant and simple.
I've used this guide before which I found pretty useful for learning about annotations and how you can pull them out of classes and methods.
You will have to define your own Annotations which is done using #interface. Then you will have to define some kind of class for doing bindings e.g. where you see an interface bind in this concrete class. Finally, you will need some logic to pull it altogether e.g. go through each class, find each annotation, and then find a suitable binding.
Give consideration to things like lazy instantiation through Reflections and singletons. Guice, for example, allows you to use a singleton so your only using one instance of the concrete class, or you can bind a new version each time.
Good luck!
Have a look at the following methods:
java/lang/Class.html#getAnnotation(java.lang.Class)
java/lang/Class.html#getAnnotations()
java/lang/Class.html#getDeclaredAnnotations()
Methods of the same name also exist for the java/lang/reflect/Method, java/lang/reflect/Field and java/lang/reflect/Constructor classes.
So in order to use these sorts of methods, you need to know a bit about Java reflection.

Do I need to create custom ClassLoaders to support new archives format?

I need to support loading classes from other types of archives(tar.gz,tar.bz2...) and custom types defined by third parties. Do I need to override the 'loadClass' method to achieve that? (Perhaps theres another extension point for doing this? I still want to benefit from all the security checks made by the default class loaders).
Unfortunately there's no standard class loader that delegates to a simple class name to byte[]/ByteBuffer interface. You'll need to either do your own class loader, save to an icky temporary file or, I believe, give URLClassLoader.newInstance a URL with a custom URLHandler.

Categories