The meaning of bindings annotation with provider methods - java

Now I'm reading Guice's official document and I saw this code.
#Provides #PayPal
CreditCardProcessor providePayPalCreditCardProcessor(
#Named("PayPal API key") String apiKey) {
PayPalCreditCardProcessor processor = new PayPalCreditCardProcessor();
processor.setApiKey(apiKey);
return processor;
}
In above code, what does #PayPal mean?
In the page of the document, I understand the meaning of original binding annotations. We can customize it. But the usage is like this.
#Inject
public RealBillingService(#PayPal CreditCardProcessor processor,
TransactionLog transactionLog)
In the code, #PayPal means this parameter processor should be injected the instance indicated by the annotation.
So, what exactly does it mean in the first code?

In the first code, it means "when you find CreditCardProcessor annotated with #Paypal, use this method as provider".
Concretely, the first one is used to define the binding, the second one is used to request the binding.
The first one, could be rewritten as a rule in the configure() method:
protected void configure() {
PayPalCreditCardProcessor processor = new PayPalCreditCardProcessor();
processor.setApiKey(apiKey);
bind(CreditCardProcessor.class).annotatedWith(PayPal.class).toInstance(processor);
}
But... you actually can't because then you'd have a singleton. Never it was written that you wanted a singleton.
So the provide methods are the nice tool to allow you making new instances and initializing them before passing them around.

Think of the annotation as part of the method's return type. The #Provides method you listed does not simply provide a CreditCardProcessor, it provides a #PayPal CreditCardProcessor. Thus, the method is written #Provides #PayPal CreditCardProcessor.
You can then request #PayPal CreditCardProcessor as in your second usage, by annotating a parameter in an #Inject-annotated method or constructor, or by adding the annotation to an #Inject-annotated field. (You can also request it directly from an Injector instance by creating a Key.)

Related

Guice JIT annotated binding [duplicate]

Suppose I have a class that looks like this:
public class MyClass {
#Inject
public MyClass(#Foo("whatever") Bar dependency) {
// ...
}
}
And I wanted to have some custom logic that can see we're injecting an object of type Bar with an annotation of type #Foo("whatever") and construct a corresponding Bar object...something like a Guice Provider, but that gets more context information about the injection site. Does Guice let me do something like that?
What you're describing isn't possible through normal Guice: Providers are intended to be zero-argument pure functions and there's no way to plumb the injection site information into them as you would a flexible callback function.
You can approximate what you want, though, two different ways:
If you know every single possible value of #Foo's parameter, you can make your #Foo a binding annotation and bind it by providing a Annotation-compatible equals and hashCode. This provides the most intuitive experience: You can do anything with your #Foo you can do with any other type, such as using #Foo in constructors or injecting #Foo("value") Provider<Bar> barProvider.
#Override public void configure() {
for (String value : PREDEFINED_VALUES) {
bind(Bar.class)
.annotatedWith(new FooImpl(value))
.toProvider(new BarProvider(value));
}
}
If you want #Foo to work for arbitrary parameters, you'll need to extend Guice with custom injections. This won't work for constructor injection or alongside any other #Inject annotations, but it will allow you to inspect types after Guice injection is finished to augment them as you see fit (e.g. detecting and reacting to #Foo annotations on fields).
See the example in the Guice docs for more information there.
Internally, Guice's core is effectively a Map<Key, Provider>, where a Key represents a pair of a possibly-parameterized type and an optional binding annotation. The former binding annotation trick works because Guice can map your injection request to a Provider all on its own, where the latter skips Guice's map so you can inspect/construct/inject instances all on your own.
If you're willing to skip the annotation part of your solution, you could inject a BarProvider or BarFactory that exposes a forFoo(String) method, which would give you consistent injection without knowing all your String values ahead of time. This would allow you to use assisted injection or AutoFactory to generate your factory (if you want to generate one instance per call), or let you write a straightforward factory yourself for added flexibility.
public class MyClass {
private final Bar dependency;
#Inject
public MyClass(BarProvider barProvider) {
dependency = barProvider.forFoo("whatever");
// ...
}
}

execute some code before and after of any method execution only by giving my custom annotation in java

I am trying to write a code for custom annotation. when I use this annotation on any method, then before execution and after execution of method some simple print msg should execute. I tried like this :
import java.lang.annotation.*;
#Retention(RetentionPolicy.RUNTIME)
#interface DemoAnnotation {
String value();
String value1();
}
// Applying annotation
class CustomAnnotationExample {
#DemoAnnotation(value = "code is started!!!", value1= "code is completed!!!")
public void sayHello() {
System.out.println("hello Annotation Example");
}
}
and in another main method I called it like :
CustomAnnotationExample h=new CustomAnnotationExample();
Method m=h.getClass().getMethod("sayHello");
DemoAnnotation anno=m.getAnnotation(DemoAnnotation.class);
System.out.println(anno.value());
h.sayHello();
System.out.println(anno.value1());
I want to print values from annotation without using System.out.println() in main method . when I just call sayHello() method . annotation values should get printed before and after execution of sayHello() method.
Please help me on this.
There are two ways, both of them very complex, runtime and compile time solution:
The runtime solution relies on specific framework which is used to instantiate the application. The common way is to create wrapping proxies for the final object and do the stuff from the proxy before (or after) calling the original object method.
For spring for example the solution is to register BeanPostProcessor object which would intercept the instantiation of the bean and check whether some of the method contains the DemoAnnotation annotation. In case it does, it would create a proxy to that object and return the proxy as the real bean.
Second solution is compile time solution and is based on annotation processors which can modify the java compiler behavior. You need to create and register annotation processor and after parsing the source file checking the annotations on the method and add the relevant code during the compilation time. There are many helpers, you can for example register on TreeScanner.visitMethod() method and invoke the TreeScanner from your annotation processor.
Generally the good example can be found in lombok which does similar things in terms of modifying the code during the compile time.

How can I make Spring Framework 's #Cachable work with lastModified property of a File as key?

This is the code I have:
#Cacheable(value = "configurationCache", key = "#myFile.lastModified()")
private Object foo(File myFile) throws IOException {
System.out.println(myFile.lastModified());
try {
Thread.sleep(6000);
} catch (InterruptedException ignored) {
}
final Object foo = new SomeObjectFromFile(myFile);
return foo;
}
I call this method twice passing file objects that have the same lastmodified value but caching does not work, the method will wait for 6 seconds.
Here is the output I am getting:
1456298573000
1456298573000
What am I doing wrong?
key = "#myFile.lastModified"
did not work either..
I am sure my configuration with ehcache is fine.
Juliens answer is probably the right one assuming you do not use aspectj. its not alone invoking a public method, but invoking a public method of an object where spring had the chance to wrap it's proxies around. So make sure you are injecting the service that you want to have enhanced with cacheable support.
For example
#Service
public SomeService {
#Autowired
private CacheEnhancedService css;
public void doSomething() {
css.getConfig(new File("./file"));
}
}
#Service
public CacheEnhancedService {
#Cacheable(value = "configurationCache", key = "#myFile.lastModified()")
public Object getConfig(File myFile) {
...
}
}
}
The issue lies with the fact that your method is private.
As mentioned in the documentation of the Spring Framework:
Method visibility and cache annotations
When using proxies, you should apply the cache annotations only to
methods with public visibility. If you do annotate protected, private
or package-visible methods with these annotations, no error is raised,
but the annotated method does not exhibit the configured caching
settings. Consider the use of AspectJ (see below) if you need to
annotate non-public methods as it changes the bytecode itself.
[...]
In proxy mode (which is the default), only external method calls
coming in through the proxy are intercepted. This means that
self-invocation, in effect, a method within the target object calling
another method of the target object, will not lead to an actual
caching at runtime even if the invoked method is marked with
#Cacheable - considering using the aspectj mode in this case. Also,
the proxy must be fully initialized to provide the expected behaviour
so you should not rely on this feature in your initialization code,
i.e. #PostConstruct.
You should either switch to a public method and make and external call or user AspectJ.

Can I use some kind of assisted Inject with Dagger?

With Google Guice or Gin I can specify parameter with are not controlled by the dependency injection framework:
class SomeEditor {
#Inject
public SomeEditor(SomeClassA a, #Assisted("stage") SomeClassB b) {
}
}
The assisted parameter stage is specified at the time an instance of SomeEditor is created.
The instance of SomeClassA is taken from the object graph and the instance of SomeClassB is taken from the caller at runtime.
Is there a similar way of doing this in Dagger?
UPDATE: As of Dagger 2.31 from January 2021, Dagger now natively supports assisted injection, which is recommended over the Square and Auto options. (Those other options still work, but may require extra setup compared to the native option.)
class SomeEditor {
#AssistedInject public SomeEditor(
SomeClassA a, #Assisted SomeClassB b) {
// ...
}
}
#AssistedFactory interface SomeEditorFactory {
SomeEditor create(SomeClassB b);
}
(original answer)
Because factories are a separate type of boilerplate to optimize away (see mailing list discussion here), Dagger leaves it to a sister project, AutoFactory. This provides the "assisted injection" functionality Guice offers via FactoryModuleBuilder, but with some extra benefits:
You can keep using AutoFactory with Guice or Dagger or any other JSR-330 dependency injection framework, so you can keep using AutoFactory even if you switch between them.
Because AutoFactory generates code, you don't need to write an interface to represent the constructor: AutoFactory will write a brand new type for you to compile against. (You can also specify an interface to implement, if you'd prefer, or if you're migrating from Guice.)
Because all the type inspection happens at compile-time, it produces plain old Java, which doesn't have any slowness due to reflection and which works well with debuggers and optimizers. This makes the Auto library particularly useful for Android development.
Example, pulled from AutoFactory's README, which will produce a SomeClassFactory with providedDepA in an #Inject-annotated constructor and depB in a create method:
#AutoFactory
final class SomeClass {
private final String providedDepA;
private final String depB;
SomeClass(#Provided #AQualifier String providedDepA, String depB) {
this.providedDepA = providedDepA;
this.depB = depB;
}
// …
}
Just like #xsveda, I also wrote an answer about this in this other question, which I'll also reproduce here.
Today, for assisted injection with Dagger you probably want to use AssistedInject. I wrote about it in this blogpost, but I'll add a full example here to make things easier.
First thing you need are the dependencies:
compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.4.0'
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.4.0'
Then here's how it can look like:
class ImageDownloader #AssistedInject constructor(
private val httpClient: HttpClient,
private val executorService: ExecutorService,
#Assisted private val imageUrl: URL,
#Assisted private val callback: ImageCallback
) {
#AssistedInject.Factory
interface Factory {
fun create(imageUrl: URL, callback: ImageCallback): ImageDownloader
}
}
First thing is that instead of annotating the constructor with #Inject, we annotate it with #AssistedInject. Then we annotate the parameters that will have to go through the factory, which is the opposite of what AutoFactory expects. Finally, we need an inner factory interface annotated with #AssistedInject.Factory that has a single method that receives the assisted parameters and returns the instance we're interested in.
Unfortunately, we still have an extra step here:
#AssistedModule
#Module(includes = [AssistedInject_AssistedInjectModule::class])
interface AssistedInjectModule
We don't necessarily need a dedicated module for it, even though that's a valid option. But we can also have those annotations in another module that is already installed in the component. The nice thing here is that we only need to do it once, and after that any factory will automatically become part of the graph.
With that, you can basically inject the factory and ask for your object as you'd normally do.
Yes, please check this Square project: square/AssistedInject
Currently it is not in 1.0 yet for purpose. They wait until Dagger will introduce a public API for registering those generated Module classes automatically - see this issue. With that you won't have to reference them in your Dagger code as in this example from README:
#AssistedModule
#Module(includes = AssistedInject_PresenterModule.class)
abstract class PresenterModule {}

How Dependency Injection Manually Implemented?

How we can manually inject an object without using the facility of containers. I did something similar through reflection as follows.
Class actionClass = Class.forName("SampleClass");
Object actionObject = actionClass.newInstance();
Method reqMethod = actionClass.getMethod("setRequest", HttpServletRequest.class);
reqMethod.invoke(actionObject,request);
is it the right way to do DI?
My intention is to pass request object to different controller classes dynamically from a dispatcher filter,where we get request and response objects.
I am fearing about the performace of reflection.Is there any replacement for doing DI?
Dependency injection is nothing more than providing a class with its dependencies, rather than have it find them itself (via singletons/lookups etc.). So you can do it in code trivially thus:
DatabaseConnection dc = new DatabaseConnection();
MyDAO dao = new MyDAO(dc);
(pseudocode). Here the MyDAO is being injected with a database connection. If that database connection implements an interface you can easily mock this out during testing.
Well, when you set one object into another object using setter method or through a constructor it also is the dependency injection. Dependency injection only means creating relationship(dependency) in objects.
Using reflection as you did is just another form of it.
Why would you use reflection? Why not simply:
SampleClass action = new SampleClass();
action.setRequest(request);
That does the same thing, but is more readable, allows the compiler to check that the types and methods actually exist, provides you with Javadoc for the Method invoked, enables your IDE to assist in refactorings, ...
And it still is dependency injection, because the action doesn't go looking for its request, but receives the request during initialization.
Edit: Thorbjørn requested I show how that action would be used. It would itself be injected (using a setter) into whatever component uses the action. The component would then use the injected action object.
SampleClass action = new SampleClass();
action.setRequest(request);
Servlet servlet = new ActionBasedServlet();
servlet.setAction(action);
If servlet is intended to live longer than action, i.e. it should use a fresh Action each time it needs one, one can instead setter-inject an ActionFactory into servlet.
In this concrete case, I'd question whether the action really needs to keep a request as part of its state, or can be immutable and simply act on the request passed by the Servlet as method parameter. In that case, the boot-time initialization would do:
SampleClass action = new SampleClass();
Servlet servlet = new ActionBasedServlet();
servlet.setAction(action);
and ActionBasedServlet would define
public void serve(Request req, Response resp) {
foo();
action.act(req, resp);
bar();
}
Dependency Injection implies you get properly initialized references appearing "by magic".
You call the setRequest() method with the request object, but DI frequently also allows for setting the fields without invoking methods.
Guice does not as such require a container, but uses class loader magic started in the main method. Would that be useable for you?
Spring framework is one of the most popular DI implementations. It is also opensource.
You can check out the class org.springframeowrk.beans.BeanUtils, specifically the methods copyProperties (all 4 of them) for examples on how to do this.
For more info you can also see the class hierarchy of org.springframework.beans.factory.BeanFactory for different strategies.

Categories

Resources