While reading AEM documentation about using models,
I couldn't figure out what is the difference between #Inject and #ValueMapValue annotation above the field.
I tried using both, and they both seems the same, so I must be missing something.
They are not the same, #Inject is a general purpose annotation that makes the value available from a number of injectors.
#ValueMapValue is an injector specific annotation that will specifically pick value from valuemap injector. It is equivalent to #Inject #Source("valuemap")
When the injected value is available only from one injector, their behavior would be the same, however if the same property is provided by two different injectors (say script-binding and valuemap) they might inject different values. Read more here.
Related
A tonne of code at my company uses the javax.inject.Named annotation with the default value, which the Javadoc indicates is the empty string "".
For example:
#Named
public class Foo {
...
}
This does not appear to add any value, since the empty string doesn't have any semantic meaning. If I remove the #Named annotations will there be any harmful effects?
The question What is javax.inject.Named annotation supposed to be used for? describes how #Named functions, but doesn't explain any special significance of the empty string, or why it would be necessary or beneficial to omit the actual name.
The question When should you explicitly name a Managed Bean? likewise talks about when you would want to use names to differentiate injectable beans, but doesn't provide any rationale for the use of the empty string as a name.
Can I delete these un-named #Named annotations without breaking anything?
#Named (javax.inject.Named) is equivalent of #Component (org.springframework.stereotype.Component).
When used to annotated a class, it indicates that the class will be scanned and registered. If name is not given, DI framework will use the class type when injecting dependencies.
In short, you can't remove those #Named annotation. If you do, everything will be compiled as normal. However, at runtime, you'll get runtime error something like cannot find bean xyz.
It's impossible to know if you will break anything without analyzing all the code that constructs injection keys and all the code that injects any of these bindings.
In some JSR-330 implementations (e.g. Dagger) it's not possible to use a #Named annotation with a value constructed at runtime, but in other implementations (e.g. Guice) it is possible and in fact commonly done.
For example, I could imagine a Guice module like:
public final class DynamicFooModule extends AbstractModule {
private final String whichFoo;
public DynamicFooModule(String whichFoo) {
this.whichFoo = whichFoo;
}
#Override
protected void configure() {
Key<Foo> fooKey = Key.get(Foo.class, Names.named(whichFoo));
Provider<Foo> fooProvider = getProvider(fooKey);
bind(Foo.class).toProvider(fooProvider);
}
}
This provides a binding for an unannotated Foo which delegates to a #Named(x) Foo, where x is determined by a constructor argument to the module -- which could be constructed at runtime, or derived from some default somewhere, etc.
You could imagine code building an injector like:
Injector injector = Guice.createInjector(
...,
new DynamicFooModule(getSelectedFooConfig()),
...);
Where getSelectedFooConfig() might return "" as a default or fallback.
In a situation like that, #Named without any name could be a reasonable fallback value to use. If your application is doing anything like that, then it is not safe to remove the #Named bindings, because an un-annotated binding is not equivalent to a binding with an empty string.
I still would argue that this is not a good design: it would be better to use a dedicated qualifier annotation for this purpose (e.g. #ConfigBased("foo-config")) rather than just using #Named. If you were doing that then you could at least identify which strings were being used (or, better yet, eschew strings and use an enum instead).
I would like to make sure if I understand this correctly. Spring needs a setter to inject a field reference? Couldn't it do it by just detecting it as a public field?
Is there an alternative to this. From what I understand Java EE's #Inject annotation can do this without any problem. But I have always been inclined more to Spring.
This depends on how you're creating your bean. Spring does not require setters. There are a number of other ways:
Autowiring (with or without Qualifiers) via annotation at the field level
Constructor injection (either by xml or annotations in the code)
Public fields (as you suggested) might work, though i have never tried it, and would advise against it even if it does.
Unfortunately, the XML approach does not look into private fields (that i know of). You either need to add a setter, use the constructor, or set up some sort of autowiring.
Keep in mind, autowiring can be combined with XML. Spring will pay attention to your wiring annotations even if you create your bean via xml (as opposed to something like #Component and component scanning).
It is not necessary to have Setter to inject a reference, you can use Autowire on a public variable of a class or on the setter method, u can also inject beans using constructor-arg which is a good way of injecting dependencies and autowiring can be done on Constructors also. #inject also does the same functionality as #autowired, however #Autowired has an additional behaviour where it internally also uses #required attribute, to see if the bean has a references and injected properly.
Spring provides several alternatives for DI besides setter injection. For example, you can use constructor injection. Alternatively, you can use Spring's #Autowired annotation for constructor, field or setter injection. Since you mentioned it, I guess that you would also be interested in knowing that Spring supports the #Inject annotation.
Is it possible to make the BeanFactoryPostProcessor detects if beans classes have methods annotated with a custom annotation (#inject for instance) and proceed to make a certain treatment if it's the case ?
If this is not possible, can you explain how i get access to the beans metadata and exploit it in the BeanFactoryPostProcessor ?
Thanks in advance.
Edit: I came across this link, not sure if it's the right solution though, since i heard that using reflections considerably deteriorates the overall application performance.
The ConfigurableListableBeanFactory passed into the postProcessBeanFactory() method call, has a method getBeanDefinition(String), from which you can get the class name of that bean. From here you can do a Class.forName(String), and get the class, and then you can inspect its members for your annotation. Of course this suggestion uses Java Reflection also.
You could also try to annotate each class that you want to inspect with its own custom annotation. From the ConfigurableListableBeanFactory you can then call getBeansWithAnnotation(Class). This returns a map from beanName to the corresponding instance.
Or you can take a look at the JavaDoc yourself:
http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/config/ConfigurableListableBeanFactory.html
Which annotation, #Resource (jsr250) or #Autowired (Spring-specific) should I use in DI?
I have successfully used both in the past, #Resource(name="blah") and #Autowired #Qualifier("blah")
My instinct is to stick with the #Resource tag since it's been ratified by the jsr people.
Anyone has strong thoughts on this?
Both #Autowired (or #Inject) and #Resource work equally well. But there is a conceptual difference or a difference in the meaning
#Resource means get me a known resource by name. The name is extracted from the name of the annotated setter or field, or it is taken from the name-Parameter.
#Inject or #Autowired try to wire in a suitable other component by type.
These are two quite distinct concepts. Unfortunately, the Spring-Implementation of #Resource has a built-in fallback, which kicks in when resolution-by-name fails. In this case, it falls back to the #Autowired-kind resolution-by-type. While this fallback is convenient, it causes a lot of confusion, because people are unaware of the conceptual difference and tend to use #Resource for type-based autowiring.
In spring pre-3.0 it doesn't matter which one.
In spring 3.0 there's support for the standard (JSR-330) annotation #javax.inject.Inject - use it, with a combination of #Qualifier. Note that spring now also supports the #javax.inject.Qualifier meta-annotation:
#Qualifier
#Retention(RUNTIME)
public #interface YourQualifier {}
So you can have
<bean class="com.pkg.SomeBean">
<qualifier type="YourQualifier"/>
</bean>
or
#YourQualifier
#Component
public class SomeBean implements Foo { .. }
And then:
#Inject #YourQualifier private Foo foo;
This makes less use of String-names, which can be misspelled and are harder to maintain.
As for the original question: both, without specifying any attributes of the annotation, perform injection by type. The difference is:
#Resource allows you to specify a name of the injected bean
#Autowired allows you to mark it as non-mandatory.
The primary difference is, #Autowired is a spring annotation. Whereas #Resource is specified by the JSR-250, as you pointed out yourself. So the latter is part of Java whereas the former is Spring specific.
Hence, you are right in suggesting that, in a sense. I found folks use #Autowired with #Qualifier because it is more powerful. Moving from some framework to some other is considered very unlikely, if not myth, especially in the case of Spring.
I would like to emphasize one comment from #Jules on this answer to this question. The comment brings a useful link: Spring Injection with #Resource, #Autowired and #Inject. I encourage you to read it entirely, however here is a quick summary of its usefulness:
How annotations select the right implementation?
#Autowired and #Inject
Matches by Type
Restricts by Qualifiers
Matches by Name
#Resource
Matches by Name
Matches by Type
Restricts by Qualifiers (ignored if match is found by name)
Which annotations (or combination of) should I use for injecting my beans?
Explicitly name your component [#Component("beanName")]
Use #Resource with the name attribute [#Resource(name="beanName")]
Why should I not use #Qualifier?
Avoid #Qualifier annotations unless you want to create a list of similar beans. For example you may want to mark a set of rules with a specific #Qualifier annotation. This approach makes it simple to inject a group of rule classes into a list that can be used for processing data.
Does bean injection slow my program?
Scan specific packages for components [context:component-scan base-package="com.sourceallies.person"]. While this will result in more component-scan configurations it reduces the chance that you’ll add unnecessary components to your Spring context.
Reference: Spring Injection with #Resource, #Autowired and #Inject
This is what I got from the Spring 3.0.x Reference Manual :-
Tip
If you intend to express annotation-driven injection by name, do
not primarily use #Autowired, even if is technically capable of
referring to a bean name through #Qualifier values. Instead, use the
JSR-250 #Resource annotation, which is semantically defined to
identify a specific target component by its unique name, with the
declared type being irrelevant for the matching process.
As a specific consequence of this semantic difference, beans that are
themselves defined as a collection or map type cannot be injected
through #Autowired, because type matching is not properly applicable
to them. Use #Resource for such beans, referring to the specific
collection or map bean by unique name.
#Autowired applies to fields, constructors, and multi-argument
methods, allowing for narrowing through qualifier annotations at the
parameter level. By contrast, #Resource is supported only for fields
and bean property setter methods with a single argument. As a
consequence, stick with qualifiers if your injection target is a
constructor or a multi-argument method.
#Autowired + #Qualifier will work only with spring DI, if you want to use some other DI in future #Resource is good option.
other difference which I found very significant is #Qualifier does not support dynamic bean wiring, as #Qualifier does not support placeholder, while #Resource does it very well.
For example:
if you have an interface with multiple implementations like this
interface parent {
}
#Service("actualService")
class ActualService implements parent{
}
#Service("stubbedService")
class SubbedService implements parent{
}
with #Autowired & #Qualifier you need to set specific child implementation
like
#Autowired
#Qualifier("actualService") or
#Qualifier("stubbedService")
Parent object;
which does not provide placeholder while with #Resource you can put placeholder and use property file to inject specific child implementation like
#Resource(name="${service.name}")
Parent object;
where service.name is set in property file as
#service.name=actualService
service.name=stubbedService
Hope that helps someone :)
Both of them are equally good. The advantage of using Resource is in future if you want to another DI framework other than spring, your code changes will be much simpler. Using Autowired your code is tightly coupled with springs DI.
When you analyze critically from the base classes of these two annotations.You will realize the following differences.
#Autowired uses AutowiredAnnotationBeanPostProcessor to inject dependencies.
#Resource uses CommonAnnotationBeanPostProcessor to inject dependencies.
Even though they use different post processor classes they all behave nearly identically.
The differences critically lie in their execution paths, which I have highlighted below.
#Autowired / #Inject
1.Matches by Type
2.Restricts by Qualifiers
3.Matches by Name
#Resource
1.Matches by Name
2.Matches by Type
3.Restricts by Qualifiers (ignored if match is found by name)
With #Resource you can do bean self-injection, it might be needed in order to run all extra logic added by bean post processors like transactional or security related stuff.
With Spring 4.3+ #Autowired is also capable of doing this.
#Resource is often used by high-level objects, defined via JNDI. #Autowired or #Inject will be used by more common beans.
As far as I know, it's not a specification, nor even a convention. It's more the logical way standard code will use these annotations.
As a note here:
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext and SpringBeanAutowiringSupport.processInjectionBasedOnServletContext DOES NOT work with #Resource annotation. So, there are difference.
I am trying to let a piece of runtime state decide WHICH implementation of an interface to use, preferably solely by autowiring.
I have tried making an object factory for the interface thet uses dynamic proxies, and I used qualifiers to coerce the #Autowired injections to use the factory. The qualifiers are necessary because both the factory and the implementations respond to the same interface.
The problem with this is that I end up annotating every #Autowired reference with the #Qualifier. What I'd really want to do is annotate the non-factory implementations with something like #NotCandidateForAutowiringByInterface (my fantasy annotation), or even better make spring prefer the single un-qualified bean when injecting to an un-qualified field
I may thinking along the totally wrong lines here, so alternate suggestions are welcome.
Anyone know how to make this happen ?
You could use #Resource and specify the bean name of the factory.
I haven't looked at this myself but I noticed Spring JavaConfig is made it to M4 and it seems to allow more flexible configuration through a combination of annotations and Java code. I wonder if it would offer a solution to your problem.