Spring Bean implemented by a 3rd party library that uses #Inject conflicting with Spring's injection mechanism - spring-boot

I am trying to have a #Bean implemented by a class from a 3rd party library (OWL API).
This implementation uses an #Inject annotation. Spring tries to interpret it, interfering with the injection mechanism of the 3rd party library and avoiding it to work as intended.
Is there a way to instruct Spring to ignore the #Inject annotations of the bean implementation, when instantiating the bean?
I found few questions about this subject but none of them provided a solution usable in my context.
I actually managed to resolve the issue myself, by wrapping the 3rd party object in an anonymous class, apparently creating a barrier for Spring and preventing it to look into this object (see the point 3. below), but I consider it to be an ugly workaround.
Details:
According to the OWL API documentation, the OWLOntologyManager is to be created like this:
OWLOntologyManagerFactory ontologyManagerFactory = new OWLManager();
OWLOntologyManager owlOntologyManager = ontologyManagerFactory.get();
//... use owlOntologyManager
Indeed, in my Spring application that was working. However, I need to have the OWLOntologyManagerFactory with an application scope and OWLOntologyManager with a Session scope.
So I declared each of these two objects as a Spring #Bean, with an appropriate scope and started to receive an error:
Error creating bean with name 'scopedTarget.sessionOWLOntologyManager': Unsatisfied dependency expressed through method 'setIRIMappers' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.util.Set' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
See below samples of the code.
Functional first test of the code, not meeting the application needs:
#RestController
public class OntologiesController {
#RequestMapping("ontologies")
public String manager_loadOntology(
#RequestParam(value="ontologyIriString") String ontologyIriString
) throws OWLOntologyCreationException
{
OWLOntologyManagerFactory ontologyManagerFactory = new OWLManager();
OWLOntologyManager owlOntologyManager = ontologyManagerFactory.get();
OWLOntology ontology = owlOntologyManager.loadOntology(IRI.create(ontologyIriString));
return ontology.toString();
}
}
Not functional code failing to create OWLOntologyManager with the error quoted above.
#Configuration
public class ApplicationScopeConfig {
#Bean
#ApplicationScope
public OWLOntologyManagerFactory applicationOWLOntologyManagerFactory() {
return new OWLManager();
}
}
#Configuration
public class SessionScopeConfig {
#Autowired
OWLOntologyManagerFactory applicationOWLOntologyManagerFactory;
#Bean
#SessionScope
public OWLOntologyManager sessionOWLOntologyManager() {
return applicationOWLOntologyManagerFactory.get();
}
}
#RestController
public class OntologiesController {
#Autowired
private OWLOntologyManager sessionOWLOntologyManager;
#RequestMapping("ontologies")
public String manager_loadOntology(
#RequestParam(value="ontologyIriString") String ontologyIriString
) throws OWLOntologyCreationException
{
OWLOntology ontology = sessionOWLOntologyManager.loadOntology(IRI.create(ontologyIriString));
return ontology.toString();
}
}
Functional code, working as needed, but ugly, is there a way to improve it?
In the code from the point 2 I modified the sessionOWLOntologyManager() as follows, wrapping it to an anonymous class that prevents Spring to look into the real owlOntologyManager.
#Bean
#SessionScope
public OWLOntologyManager sessionOWLOntologyManager() {
final OWLOntologyManager owlOntologyManager = applicationOWLOntologyManagerFactory.get();
return new OWLOntologyManager() {
public void clearOntologies() {
owlOntologyManager.clearOntologies();
}
//additional 400 lines implementing all methods by delegating to owlOntologyManager
//Apparently that creates a barrier for Spring so it does not conflict with the
//#Inject annotation in the implementation of the original owlOntologyManager,
//but in spite of having IDE support to generate this delegation, I consider it
//as an workaround.
}
}

As it eventually turns out that this is related to Configuring Spring to ignore dependencies annotated with #Inject, so I assume that a chance to get better answers is low and I post my additional findings in a reply to myself.
The class responsible for recognizing the #Inject is org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor. With my Spring knowledge I was however not able to intercept its behavior. The class SpringBeanAutowiringInterceptor, mentioned in the related question, does not exist in Spring 5.
For now I go with an improvement to my solution in the point 3. Instead of generating dozens of delegating methods (it can be done automatically by IDE), I go with the code below, using the reflection. The advantage is that it will be more resistant to changes if I should upgrade the OWLAPI library one day. Also it has significantly less lines. I assume that the reflection might be less performant.
#Bean
#SessionScope
public OWLOntologyManager sessionOWLOntologyManager() {
final OWLOntologyManager owlOntologyManager = applicationOWLOntologyManagerFactory.get();
//Instead of returning owlOntologyManager directly,
//the delegating proxy prevents Spring to resolve #Inject annotations
//in the implementation of owlOntologyManager.
return (OWLOntologyManager)Proxy.newProxyInstance(
owlOntologyManager.getClass().getClassLoader(),
owlOntologyManager.getClass().getInterfaces(),
(o, method, args) ->
method.invoke(owlOntologyManager, args)
);
}

Related

Spring #Cachable method within the same class (self-invocation, proxy issue) - What is the best way to solve it?

I'm trying to call a #Cacheable method from within the same class.
And it didn't work. Because of:
In proxy mode (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 that calls another method of the target object) does not lead to actual caching at runtime even if the invoked method is marked with #Cacheable. Consider using the aspectj mode in this case. Also, the proxy must be fully initialized to provide the expected behavior, so you should not rely on this feature in your initialization code (that is, #PostConstruct).
It means, #Cachable(also #Transactional) works by proxy classes which is Spring AOP in. a internal call in the same class make call by 'this' instead of proxy classes.
To solve the problem, I should call a method by proxy or using AspectJ(another AOP).
So, I found 4 solutions.
What is your choice? and why others are not recommended?
Please, share your opinion!
using AspectJ (another AOP)
get the Bean from ApplicationContext and use it
#Service
public class UserService implements Service {
#Autowired
private ApplicationContext applicationContext;
private Service self;
#PostConstruct
private void init() {
self = applicationContext.getBean(UserService.class);
}
}
self-autowiring using #Resource //since Spring 4.3
#Component
#CacheConfig(cacheNames = "SphereClientFactoryCache")
public class CacheableSphereClientFactoryImpl implements SphereClientFactory {
/**
* 1. Self-autowired reference to proxified bean of this class.
*/
#Resource
private SphereClientFactory self;
#Override
#Cacheable(sync = true)
public SphereClient createSphereClient(#Nonnull TenantConfig tenantConfig) {
// 2. call cached method using self-bean
return self.createSphereClient(tenantConfig.getSphereClientConfig());
}
#Override
#Cacheable(sync = true)
public SphereClient createSphereClient(#Nonnull SphereClientConfig clientConfig) {
return CtpClientConfigurationUtils.createSphereClient(clientConfig);
}
}
make the Bean scope of the class as 'prototype' instead of 'singleton'
#Service
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
class AService {
private final AService _aService;
#Autowired
public AService(AService aService) {
_aService = aService;
}
#Cacheable("employeeData")
public List<EmployeeData> getEmployeeData(Date date){
..println("Cache is not being used");
...
}
public List<EmployeeEnrichedData> getEmployeeEnrichedData(Date date){
List<EmployeeData> employeeData = _aService.getEmployeeData(date);
...
}
}
I'm a newbie in spring :)
Actually, I choose the 4th solution, but I felt it isn't a good way. because I just need to call the caching method by proxy, and it make several beans to achieve it.
After reading articles, I think AspectJ is the best choice. It looks cool, Spring recommends it, and many people also recommend too.
But I don't understand how to AspectJ works (I will study) and I also don't know why others is not recommended.
references
Spring Cache #Cacheable - not working while calling from another method of the same bean
Spring cache #Cacheable method ignored when called from within the same class
https://spring.io/blog/2012/05/23/transactions-caching-and-aop-understanding-proxy-usage-in-spring
https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#cache

Spring Proxy Creation of Classes annotated with #Configuration or #Component

Spring uses either JDK dynamic proxies or CGLIB to create the proxy for a given target object. If a class is annotated with #Configuration, then CGLIB is used.
However, one limitation of Spring AOP is that once the call has finally reached the target object, any method calls that it may make on itself are going to be invoked against the this reference, and not the proxy. This piece of information is important to remember when using #Transactional and in other places as well.
So having that knowledge, in the code below, is Spring injecting the actual instance or the proxy of SimpleBean?
#Configuration
public class Config {
#Bean
public SimpleBean simpleBean() {
return new SimpleBean();
}
#Bean
public SimpleBeanConsumer simpleBeanConsumer() {
return new SimpleBeanConsumer(simpleBean()); //<---
}
}
And what is the behavior if a class is annotation with #Component?
Let me give you another perspective.
Say there is an another bean AnotherBeanConsumer that also needs a simpleBean. Simple Bean has a Singleton scope:
#Configuration
public class Config {
#Bean
public SimpleBean simpleBean() {
return new SimpleBean();
}
#Bean
public SimpleBeanConsumer simpleBeanConsumer() {
return new SimpleBeanConsumer(simpleBean());
}
#Bean
public AnotherBeanConsumer anotherBeanConsumer() {
return new AnotherBeanConsumer(simpleBean());
}
}
Now the question is, how its possible that two calls to simpleBean() made from different methods simpleBeanConsumer and anotherBeanConsumer return the same instance of the simple bean (since its a singleton obviously)?
IMO (and disclaimer, I'm not affiliated with spring or something), This is the main reason of creating proxies that wrap Configurations.
Now indeed Spring AOP has a limitation of calling methods just as you've stated, however who said that spring under-the-hood uses spring AOP? The bytecode instrumentation done on much lower levels doesn't have a limitation like this. After all creating a proxy means: "create a proxy object that will have the same interface but will alter the behavior", right?
For example if you use CGLIB that uses inheritance you could create a proxy out of configuration that looks like this (schematically):
class CGLIB_GENERATED_PROXY extends Config {
private Map<String, Object> singletonBeans;
public SimpleBean simpleBean() {
String name = getNameFromMethodNameMaybePrecached();
if(singletonBeans.get(name) != null) {
return singletonBeans.get(name);
}
else {
SimpleBean bean = super.simpleBean();
singletonBeans.put(name, bean);
return bean;
}
}
....
}
Of course its only a schematic picture, in real life there is an application context that basically provides the access to the map like this, but you get the point.
If its not enough, then there are some even more sophisticated frameworks that spring must make use of in order to load a configuration (like ASM)...
Here is an example:
If you use #ConditionalOnClass(A.class) and the class doesn't really exist in runtime, how spring can load the bytecode of the configuration that uses this configuration and not fail on something like NoClassDefFoundException?
My point is that it goes far beyond the spring AOP, and has its quirks :)
Having said that, nothing that I've describe above requires the real components to be always wrapped in Proxies of any kind. So in the most trivial case, when SimpleBean does not by itself have some annotations that require proxy generation (stuff like #Cached, #Transactional and so forth), Spring won't wrap the object of that type and you'll get a plain SimpleBean object.

Spring #Autowired behavior different in tests than components

Are the rules/behaviors around #Autowired different when writing tests? It seems that with a test, you can autowire to a concrete type, but if you try the same thing inside a #Component it will fail. This is a contrived example, but it's something I ran into and am just trying to understand better.
Contrived example code:
public interface Gizmo {
void whirr();
}
#Configuration
public class GizmoConfiguration {
#Bean
#Profile("no-dependencies")
public Gizmo fooGizmoBean() {
return new FooGizmo();
}
#Bean
#Profile("!no-dependencies")
public Gizmo barGizmoBean() {
return new BarGizmo();
}
public class FooGizmo implements Gizmo {
#Override
public void whirr() {
}
}
public class BarGizmo implements Gizmo {
#Override
public void whirr() {
}
}
}
Test that runs fine:
#RunWith(SpringRunner.class)
#SpringBootTest
#ActiveProfiles(Application.Profiles.NO_DEPENDENCIES)
public class TestClass {
#Autowired
private GizmoConfiguration.FooGizmo gizmo;
#Test
public void test() {
assertNotNull(gizmo);
}
}
Component that causes java.lang.IllegalStateException: Failed to load ApplicationContext:
#Component
public class TestComponent {
#Autowired
private GizmoConfiguration.FooGizmo gizmo;
}
because of:
No qualifying bean of type 'GizmoConfiguration$FooGizmo' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Are the rules/behaviors around #Autowired different when writing
tests?
Not exactly: the rules are actually exactly the same. The difference is in terms of timing with regard to how Spring determines if a given bean is an autowire candidate.
It seems that with a test, you can autowire to a concrete type,
but if you try the same thing inside a #Component it will fail.
I understand why you would think that, since your example demonstrates that behavior, but your analysis is not exactly correct.
So let me explain...
When Spring attempts to perform autowiring for your #Component class, the only information it has about types (i.e., classes and interfaces) for beans coming from #Bean methods is the information available in an #Bean method's formal signature.
In your example, when Spring searches for so-called "autowire candidates" to inject into your #Component, Spring only sees a bean of type Gizmo for your fooGizmoBean() #Bean method. So that's why you see the "No qualifying bean of type 'GizmoConfiguration$FooGizmo'" error, which happens to be completely correct.
If you want Spring to be able to autowire your #Component using the concrete type, you will have to redefine the signature of your fooGizmoBean() #Bean method to return FooGizmo instead of Gizmo.
So, that's the first half of the story. The second half of the story is why the Spring TestContext Framework is able to perform autowiring by the concrete type for the test instance.
The reason that works is that the ApplicationContext has already been completely started (i.e., all beans have been instantiated and all #Bean methods have been invoked by the container) by the time the testing framework attempts to perform dependency injection. By that point in time, the fooGizmoBean() method has already been invoked by Spring, and Spring now knows the concrete type is actually a FooGizmo. Thus, #Autowired FooGizmo gizmo; works in the test.

How to dynamically inject a service using a runtime "qualifier" variable?

I can't find a simple way to inject a component/service given a runtime value.
I started reading # Spring's doc: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-autowired-annotation-qualifiers
but I can't find there how to variabilize the values passed to the #Qualifier annotation.
Let's say I've got a model entity with such interface:
public interface Case {
String getCountryCode();
void setCountryCode(String countryCode);
}
In my client code, I would do something like:
#Inject
DoService does;
(...)
Case myCase = new CaseImpl(); // ...or whatever
myCase.setCountryCode("uk");
does.whateverWith(myCase);
... with my service being:
#Service
public class DoService {
#Inject
// FIXME what kind of #$#& symbol can I use here?
// Seems like SpEL is sadly invalid here :(
#Qualifier("${caze.countryCode}")
private CaseService caseService;
public void whateverWith(Case caze) {
caseService.modify(caze);
}
}
I expect the caseService to be the UKCaseService (see related code below).
public interface CaseService {
void modify(Case caze);
}
#Service
#Qualifier("uk")
public class UKCaseService implements CaseService {
}
#Service
#Qualifier("us")
public class USCaseService implements CaseService {
}
So how do I "fix" all of this in the most simple / elegant / efficient way by using either/all Spring feature(s), so essentially NO .properties, NO XML, only annotations.
However I already suspect something is wrong in my DoService because Spring would need to know the "case" before injecting the caseService... but how to achieve this without the client code knowing about the caseService?!
I can't figure this out...
I already read several issues here on SO, but most of the times either they don't really have the same needs and/or config as I have, or the posted answers aren't enough satisfying to me (look like they're essentially workarounds or (old) usage of (old) Spring features).
How does Spring autowire by name when more than one matching bean is found?
=> only refers to component-like classes
Dynamically defining which bean to autowire in Spring (using qualifiers)
=> really interesting but the most elaborated answer (4 votes) is... almost 3 1/2 years-old?! (July 2013)
Spring 3 - Dynamic Autowiring at runtime based on another object attribute
=> quite similar problem here, but the answer really look like a workaround rather a real design pattern (like factory)? and I don't like implementing all the code into the ServiceImpl as it's done...
Spring #Autowiring, how to use an object factory to choose implementation?
=> 2nd answer seems interestingly but its author does not expand, so altough I know (a bit) about Java Config & stuff, I'm not really sure what he's talking about...
How to inject different services at runtime based on a property with Spring without XML
=> interesting discussion, esp. the answer, but the user has properties set, which I don't have.
Also read this:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/expressions.html#expressions-bean-references
=> I can't find expanded examples about the use of "#" in expressions. Does someone know about this?
Edit:
Found other related-to-similar issues, no one got a proper answer:
How to use #Autowired to dynamically inject implementation like a factory pattern
Spring Qualifier and property placeholder
Spring: Using #Qualifier with Property Placeholder
How to do conditional auto-wiring in Spring?
Dynamic injection in Spring
SpEL in #Qualifier refer to same bean
How to use SpEL to inject result of method call in Spring?
Factory Pattern might be a solution?
How to use #Autowired to dynamically inject implementation like a factory pattern
You can obtain your bean from the context by name dynamically using a BeanFactory:
#Service
public class Doer {
#Autowired BeanFactory beans;
public void doSomething(Case case){
CaseService service = beans.getBean(case.getCountryCode(), CaseService.class)
service.doSomething(case);
}
}
A side note. Using something like country code as bean name looks a bit odd. Add at least some prefix or better consider some other design pattern.
If you still like to have bean per country, I would suggest another approach. Introduce a registry service to get a required service by country code:
#Service
public class CaseServices {
private final Map<String, CaseService> servicesByCountryCode = new HashMap<>();
#Autowired
public CaseServices(List<CaseService> services){
for (CaseService service: services){
register(service.getCountryCode(), service);
}
}
public void register(String countryCode, CaseService service) {
this.servicesByCountryCode.put(countryCode, service);
}
public CaseService getCaseService(String countryCode){
return this.servicesByCountryCode.get(countryCode);
}
}
Example usage:
#Service
public class DoService {
#Autowired CaseServices caseServices;
public void doSomethingWith(Case case){
CaseService service = caseServices.getCaseService(case.getCountryCode());
service.modify(case);
}
}
In this case you have to add String getCountryCode() method to your CaseService interface.
public interface CaseService {
void modify(Case case);
String getCountryCode();
}
Alternatively, you can add method CaseService.supports(Case case) to select the service. Or, if you cannot extend the interface, you can call CaseServices.register(String, CaseService) method from some initialiser or a #Configuration class.
UPDATE: Forgot to mention, that Spring already provides a nice Plugin abstraction to reuse boilerplate code for creating PluginRegistry like this.
Example:
public interface CaseService extends Plugin<String>{
void doSomething(Case case);
}
#Service
#Priority(0)
public class SwissCaseService implements CaseService {
void doSomething(Case case){
// Do something with the Swiss case
}
boolean supports(String countryCode){
return countryCode.equals("CH");
}
}
#Service
#Priority(Ordered.LOWEST_PRECEDENCE)
public class DefaultCaseService implements CaseService {
void doSomething(Case case){
// Do something with the case by-default
}
boolean supports(String countryCode){
return true;
}
}
#Service
public class CaseServices {
private final PluginRegistry<CaseService<?>, String> registry;
#Autowired
public Cases(List<CaseService> services){
this.registry = OrderAwarePluginRegistry.create(services);
}
public CaseService getCaseService(String countryCode){
return registry.getPluginFor(countryCode);
}
}
According to this SO answer, using #Qualifier isn't going to help you much: Get bean from ApplicationContext by qualifier
As for an alternative strategy:
if you are spring boot, you could use #ConditonalOnProperty or another Conditional.
a lookup service, as #aux suggests
just name your beans consistently and look them up by name at runtime.
Note that your use case also appears to revolve around the scenario where beans are created on application startup, but the bean chosen needs to be resolved after the applicationContext has finished injecting the beans.

What is the magic behind Field #Autowired

I am currently improving my Spring knowledge. I wonder what really happens when I use Spring annotation #Autowire on a field.
Here is a piece of code :
OutputHelper file
#Component
public class OutputHelper {
#Autowired
#Qualifier("csvOutputGenerator")
private IOutputGenerator outputGenerator;
public void setOutputGenerator(IOutputGenerator outputGenerator) {
this.outputGenerator = outputGenerator;
}
// I can focus only on what my code do because my objects are injected
public void generateOutput(){
outputGenerator.generateOutput();
}
}
CsvOutputGenerator file
#Component
public class CsvOutputGenerator implements IOutputGenerator {
public void generateOutput(){
System.out.println("Csv Output Generator");
}
}
Application file
public static void main(String[] args) {
// Create the spring context
ApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring/spring-module.xml");
// Get the configured OutpuHelper from the spring-module.xml
OutputHelper output = (OutputHelper) context.getBean("outputHelper");
// Display output from the output configured
output.generateOutput();
}
My configuration file just contain <context:component-scan base-package="com.xxx.xxx.output"/>
When I execute this code all work fine. But what makes me surprised is when I delete the setOutputGenerator in OutPutHelper file, my piece of code keeps working. I tought that with this configuration, the OutputHelper was first created with default constructor and initialized with setter.
I expected an error because the variable outputGenerator was not be able to be initialized.
Is anyone can help me to understand ?
The idea to have fields #Autowired is questionable. It works, but it will difficult other aspects of your implementation (i.e. testing).
There are 3 types of injections:
fields - basically configured applying reflection (Field.set(Object, Object)) directly to the field:
#Autowired
private MyInterface field;
setters - with this approach the configuration of each dependency goes through a property (spring goes through all methods and execute each one annotated with #Autowired using Method.invoke(Object, Object...), thus its value is configured using its setter as follows:
#Autowired
public void setField(MyInterface value) {
this.field = value;
}
constructors - the last, and my preferable approach, the constructor injection. That one basically annotates an constructor with #Autowired and instead of using methods or fields, you can configure your bean directly on your constructor. For that spring will elect the a constructor to be used to instantiate your #Component, and it will use an #Autowired if existent or a empty params constructor, invoking it using Constructor.newInstance(Object...). Example:
#Component
public class Implementation {
private MyInterface field;
#Autowired
public Implementation(MyInterface value) {
Assert.notNull(value, "value should not be null");
this.field = value;
}
}
One of the ideas behind Inversion of Control (or Dependence Injection) is to be able to isolate a piece of code in order to provide decent test implementation support.
In order to go deeper, it is necessary to comment that during a unit test you want the class in its isolated form, all you will use with that class are basically mocks for its dependencies (injections).
So, what are the results:
If you do field injection, it will be quite costly to every single time set the beans using some reflection to configure the bean during your tests (another logic needs to be introduced to configure the bean to be tested).
With setter injection approach you will be able to use your own bean to configure it with mocks necessary to isolate your implementation and test its functionality.
And finally, with the constructor injection approach you will have not only the support to configure your bean, but you will be able to require its dependencies. This means that for every new dependency a new parameter on your constructor is added, this brings you come advantages on development time, for example, you will be able to see on development time the unit tests affected with the introduction of that new dependency (once your IDE will point it out for your).
Simple answer
Actually, the setter is useless, since the CDI use java Reflection to access fields.
It means that fields are no longer accessed by method calls.
Reflection allow iterating throught all fields of a class and check if there are annoted with a specific annotation.
In this case, if a field in your class is annoted With #Autowired (or #Inject wich is more J2E complient), the container will iterate throught searching if there is a registered bean that fits the current property.
Going deeper
When you context is starting, the container iterate classes and search all field annoted with #Inject or #Autowired.
For these fields, it search an available bean.
Here is the must simple example :
public class SpringClassInChargeOfDependencyInjection {
public void handdleInjections(T objectWithInjectableField) {
Class<T> clazz = objectWithInjectableField.class;
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Autowired.class) || field.isAnnotationPresent(Inject.class)) {
//find a bean for the type;
Object injectableBean = getAvailablebean(field.getType());
field.setAccessible(true);
//inject the value into the class, this line explain why the setter is not necessary
field.set(objectWithInjectableField, injectableBean);
}
}
}
}
This is a non-working example just to explain how it works.
Tips
You might consider using #Inject instead of #Autowired, the later was created by Spring, #Inject is a part of the the JSR-330. Spring does understand #Inject as well, you just need to add the javax.inject jar dependency to your project. If later you want to switch from spring to something else (guice for example) you won't have to change all your #Autowired annotations
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>

Resources