In spring when I do:
#Autowire
List<MyInterface> myInterfaces;
then this list will get populated by all beans which implement MyInterface. I didn't have to create bean of type List<MyInterface>.
I'm looking for such behaviour in Google Guice.
Sofar I went with:
Multibinder<MyInterface> myInterfaceBinder = MultiBinder.newSetBinder(binder(), MyInterface.class);
Now if I have a bean which implements MyInterface and I bind it, say via:
bind(MyInterfaceImpl.class).asEagerSingleton();
it won't be included in my multibinder. I need to add:
myInterfaceBinder.addBinding.to(MyInterfaceImpl.class);
This is somewhat more complicated than what Spring offers. So I was wonmdering whether I'm not using it in wrong way. So is there easier way of achieving this?
I haven't used it that way myself, yet, but according to Guice's API documentation, I think you should be able to write something not much more than this once:
bindListener(Matchers.subclassesOf(MyInterface.class), new TypeListener() {
public <I> void hear(TypeLiteral<I> typeLiteral,
TypeEncounter<I> typeEncounter) {
myInterfaceBinder.addBinding().to(typeLiteral);
}
}
Then, when you bind an implementation via
bind(MyInterfaceImpl.class).asEagerSingleton();
it should be added to your multibinder automatically.
A hacky solution would be to do it all in a loop:
Multibinder<MyInterface> myInterfaceBinder
= MultiBinder.newSetBinder(binder(), MyInterface.class);
Class<? extends MyInterface>[] classes = {
MyInterfaceImpl,
YourInterfaceImpl.class,
MyCatsInterfaceImpl
};
for (Class<? extends MyInterface> c : classes) {
bind(c).asEagerSingleton();
myInterfaceBinder.addBinding.to(c);
}
It's hacky, it's applicable for such simple cases only, but it's simple and DRY.
Related
I'm trying to understand how to handle conditionally creating new instances of a class that uses #Inject. In the below example I have a factory that instantiates classes based on a parameter.
AnimalFactory does not have access to the injector the main class of my application has, so I can't use injector.getInstance(Cat.class)
class AnimalFactory {
public IAnimal create(AnimalType type) {
if (type.equals(AnimalType.CAT)) {
return new Cat(); // Cat uses #Inject, so this won't work of course. But ???
} else if (type.equals(AnimalType.DOG)) {
return new Dog();
}
}
}
In the rest of my app, classes are injected into my constructors because I always need them. Guice creates an instance/singleton for each. But in this scenario, I do not want to create and inject instances for each animal because all but one are needed.
You can use a MapBinder as described here:
public class AnimalModule extends AbstractModule {
public void configure() {
MapBinder<AnimalType, IAnimal> animalBinder= MapBinder.newMapBinder(binder(), AnimalType.class, IAnimal.class);
animalBinder.addBinding(AnimalType.DOG).to(Dog.class);
...
}
}
And than use it in your factory:
class AnimalFactory {
#Inject
Map<AnimalType, IAnimal> animals;
public IAnimal create(AnimalType type) {
return animals.get(type);
}
}
Actually I worked on exactly the same issue and I wrote a feature that allows you to create self-populating factory. Meaning that if you work in Spring/Spring-boot environment you can create a factory that can access and provide any interface implementing class that is managed by Spring-boot without injecting in the factory. You can also give the instances custom names. So, it seems like it fits your case exactly. Here is a link to an article that describes the feature in great detail: Non-intrusive access to "Orphaned" Beans in Spring framework. Also, in MgntUtils library Javadoc there is a good description of the feature here enter link description here. The library itself including source code could be found on Github here and in the package com.mgnt.lifecycle.management.example there is a working example. Maven artifacts are here
I am using guice for dependency injection in my project. I have a few interfaces for which I have default bindings.
I want to provide the facility where the user can implement the interface and that custom implementation would be binded over default one. If no custom implementation is present Default binding should happen.
How can this be done?
I thought of a way where the user annotates the implemented classes with an annotation and I can get the interface from that and bind that class to that interface. Is this possible?
Please help.
Thank you.
when you use spring framework, you can use declare a bean with #ConditionalOnMissingBean, if not, you can try to implement like this(check whether the object has bean declared)
Probably best would be to have a BeanFactory, and the user should then provide his implementation for a given interface:
class BeanFactory {
private static final Map<Class<?>, ?> beans = new HashMap<>();
public static <T> void register(Class<T> type, T impl){
beans.put(type, impl);
}
}
That way you could have your beans initially declared in above factory and then they could get overwritten by a user.
class MyImpl implements MyService{
static{
BeanFactory.register(MyService.class, new MyImpl());
}
// Rest of code
}
also, you can use SPI
ServiceLoader<SayHello> services = ServiceLoader.load(SayHello.class);
if services is empty, you can new the default instance.
In my guice module I have multiple factories like shown below:
install(new FactoryModuleBuilder().implement(SportsCar.class,Ferrari.class).build(FerrariFactory.class));
install(new FactoryModuleBuilder().implement(LuxuryCar.class,Mercedes.class).build(MercedesFactory.class));
Both the factories have the following create method which takes an assisted element:
Ferrari create(#Assisted Element partsElement);
Mercedes create(#Assisted Element partsElement);
In a CarChooser class, I get instances of Ferrari or Mercedes as shown below:
#Inject
public CarChooser(FerrariFactory ferrariFactory , MercedesFactory mercedesFactory )
{
this.ferrariFactory = ferrariFactory;
this.mercedesFactory = mercedesFactory;
}
In the same class:
if(type.equals("ferrari"))
ferrariFactory.create(partsElement);
else if (type.equals("mercedes"))
mercedesFactory.create(partsElement);
...
Now, what I am trying is to make this CarChooser class open for extension but closed for modification. i.e. If I need to add another Factory, I shouldn't have to declare it as a variable + add it to the constructor + add another if clause for the corresponding new type. I was planning to use ServiceLoader here and declare an interface CarFactory which will be implemented by all factories (such as FerrariFactory, MercedesFactory etc.) and all implementations will have a getCarType method. But how can I call the create method using Service Loader ?
ServiceLoader<CarFactory> impl = ServiceLoader.load(CarFactory.class);
for (CarFactory fac: impl) {
if (type.equals(fac.getCarType()))
fac.create(partsElement);
}
}
Is the right way if it works (I am not even sure if this would work). Or Is there a better way of doing the same ?
Thanks to the first comment on the post, I know that I want to use MapBinder . I wrote a CarFactory which is extended by both FerrariFactory and MercedesFactory. So I add the following:
MapBinder<String, CarFactory> mapbinder = MapBinder.newMapBinder(binder(), String.class, CarFactory.class);
mapbinder.addBinding("Ferrari").to(FerrariFactory.class);
mapbinder.addBinding("Mercedes").to(MercedesFactory.class);
But since the .to portion of the above code is abstract class I get an initialisation error that FerrariFactory is not bound to any implementation. What should I have here to bind it to the correct Assisted Inject Factory declared with the FactoryModuleBuilder ?
So, using a MapBinder along with generics is the solution.
install(new FactoryModuleBuilder().implement(SportsCar.class,Ferrari.class).build(FerrariFactory.class));
install(new FactoryModuleBuilder().implement(LuxuryCar.class,Mercedes.class).build(MercedesFactory.class));
MapBinder<String, CarFactory<?>> mapbinder = MapBinder.newMapBinder(binder(), new TypeLiteral<String>(){}, new TypeLiteral<CarFactory<?>>(){});
mapbinder.addBinding("ferrari").to(FerrariFactory.class);
mapbinder.addBinding("mercedes").to(MercedesFactory.class);
The important thing here to note is that this seems to be supported only in Guice 3.0 + JDK 7. For JDK 8, you need Guice 4.0 ! Found this problem on https://github.com/google/guice/issues/904
Hope that helps.
More details regarding the solution:
http://crusaderpyro.blogspot.sg/2016/07/google-guice-how-to-use-mapbinder.html
Can I do it with reflection or something like that?
I have been searching for a while and there seems to be different approaches, here is a summary:
reflections library is pretty popular if u don't mind adding the dependency. It would look like this:
Reflections reflections = new Reflections("firstdeveloper.examples.reflections");
Set<Class<? extends Pet>> classes = reflections.getSubTypesOf(Pet.class);
ServiceLoader (as per erickson answer) and it would look like this:
ServiceLoader<Pet> loader = ServiceLoader.load(Pet.class);
for (Pet implClass : loader) {
System.out.println(implClass.getClass().getSimpleName()); // prints Dog, Cat
}
Note that for this to work you need to define Petas a ServiceProviderInterface (SPI) and declare its implementations. you do that by creating a file in resources/META-INF/services with the name examples.reflections.Pet and declare all implementations of Pet in it
examples.reflections.Dog
examples.reflections.Cat
package-level annotation. here is an example:
Package[] packages = Package.getPackages();
for (Package p : packages) {
MyPackageAnnotation annotation = p.getAnnotation(MyPackageAnnotation.class);
if (annotation != null) {
Class<?>[] implementations = annotation.implementationsOfPet();
for (Class<?> impl : implementations) {
System.out.println(impl.getSimpleName());
}
}
}
and the annotation definition:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.PACKAGE)
public #interface MyPackageAnnotation {
Class<?>[] implementationsOfPet() default {};
}
and you must declare the package-level annotation in a file named package-info.java inside that package. here are sample contents:
#MyPackageAnnotation(implementationsOfPet = {Dog.class, Cat.class})
package examples.reflections;
Note that only packages that are known to the ClassLoader at that time will be loaded by a call to Package.getPackages().
In addition, there are other approaches based on URLClassLoader that will always be limited to classes that have been already loaded, Unless you do a directory-based search.
What erickson said, but if you still want to do it then take a look at Reflections. From their page:
Using Reflections you can query your metadata for:
get all subtypes of some type
get all types annotated with some annotation
get all types annotated with some annotation, including annotation parameters matching
get all methods annotated with some
In general, it's expensive to do this. To use reflection, the class has to be loaded. If you want to load every class available on the classpath, that will take time and memory, and isn't recommended.
If you want to avoid this, you'd need to implement your own class file parser that operated more efficiently, instead of reflection. A byte code engineering library may help with this approach.
The Service Provider mechanism is the conventional means to enumerate implementations of a pluggable service, and has become more established with the introduction of Project Jigsaw (modules) in Java 9. Use the ServiceLoader in Java 6, or implement your own in earlier versions. I provided an example in another answer.
Spring has a pretty simple way to acheive this:
public interface ITask {
void doStuff();
}
#Component
public class MyTask implements ITask {
public void doStuff(){}
}
Then you can autowire a list of type ITask and Spring will populate it with all implementations:
#Service
public class TaskService {
#Autowired
private List<ITask> tasks;
}
The most robust mechanism for listing all classes that implement a given interface is currently ClassGraph, because it handles the widest possible array of classpath specification mechanisms, including the new JPMS module system. (I am the author.)
try (ScanResult scanResult = new ClassGraph().whitelistPackages("x.y.z")
.enableClassInfo().scan()) {
for (ClassInfo ci : scanResult.getClassesImplementing("x.y.z.SomeInterface")) {
foundImplementingClass(ci); // Do something with the ClassInfo object
}
}
With ClassGraph it's pretty simple:
Groovy code to find implementations of my.package.MyInterface:
#Grab('io.github.classgraph:classgraph:4.6.18')
import io.github.classgraph.*
new ClassGraph().enableClassInfo().scan().withCloseable { scanResult ->
scanResult.getClassesImplementing('my.package.MyInterface').findAll{!it.abstract}*.name
}
What erikson said is best. Here's a related question and answer thread - http://www.velocityreviews.com/forums/t137693-find-all-implementing-classes-in-classpath.html
The Apache BCEL library allows you to read classes without loading them. I believe it will be faster because you should be able to skip the verification step. The other problem with loading all classes using the classloader is that you will suffer a huge memory impact as well as inadvertently run any static code blocks which you probably do not want to do.
The Apache BCEL library link - http://jakarta.apache.org/bcel/
Yes, the first step is to identify "all" the classes that you cared about. If you already have this information, you can enumerate through each of them and use instanceof to validate the relationship. A related article is here: https://web.archive.org/web/20100226233915/www.javaworld.com/javaworld/javatips/jw-javatip113.html
Also, if you are writing an IDE plugin (where what you are trying to do is relatively common), then the IDE typically offers you more efficient ways to access the class hierarchy of the current state of the user code.
I ran into the same issue. My solution was to use reflection to examine all of the methods in an ObjectFactory class, eliminating those that were not createXXX() methods returning an instance of one of my bound POJOs. Each class so discovered is added to a Class[] array, which was then passed to the JAXBContext instantiation call. This performs well, needing only to load the ObjectFactory class, which was about to be needed anyway. I only need to maintain the ObjectFactory class, a task either performed by hand (in my case, because I started with POJOs and used schemagen), or can be generated as needed by xjc. Either way, it is performant, simple, and effective.
A new version of #kaybee99's answer, but now returning what the user asks: the implementations...
Spring has a pretty simple way to acheive this:
public interface ITask {
void doStuff();
default ITask getImplementation() {
return this;
}
}
#Component
public class MyTask implements ITask {
public void doStuff(){}
}
Then you can autowire a list of type ITask and Spring will populate it with all implementations:
#Service
public class TaskService {
#Autowired(required = false)
private List<ITask> tasks;
if ( tasks != null)
for (ITask<?> taskImpl: tasks) {
taskImpl.doStuff();
}
}
I have a bunch of entity type factories that derive from a common, generic interface. For instance,
public class ConnectionFactory implements IEntityFactory<Connection> { ... }
I'd like to use Google-Guice to break hard dependencies on these factories.
However, there's a syntax error when I try to configure Guice:
public class EntityFactoryModule extends AbstractModule {
#Override
protected void configure() {
bind(IEntityFactory<Connection>.class).to(ConnectionFactory.class);
}
}
Eclipse says "IEntityFactory cannot be resolved to a variable."
Can someone please help me understand why this doesn't work? Also, is there an alternate syntax that will work?
My Guice-fu is generally limited, but I think you want a type literal here:
bind(new TypeLiteral<IEntityFactory<Connection>>() {})
.to(ConnectionFactory.class);
One method is to declare a new interface:
interface IConnectionFactory extends IEntityFactory<Connection> { ...}
Then I can do:
bind(IConnectionFactory.class).to(ConnectionFactory.class);
But, there's already an interface explosion going on in my project.
Is there a better way?