Spring and Guice: when DI frameworks create proxies? - java

We know that DI frameworks, such as Spring and Guice sometimes create proxies instead of beans. To compare these proxies in equals and hashcode methods we should use instanceOf operator, because their class is not longer the same as the original one.
Also (may be) these proxies may be created in some uninitialized state just like Hibernate proxies (its just my guess).
I know only one case when Spring creates proxy of a bean: when you annotate it with #Configuration.
Is there any other situations like that?
Does Spring create uninitialized proxies which only initialize their fields once that fields are accessed?
I have found a similair question: When does Spring creates proxies in the bean's lifecycle?, but please note that it relates to AOP usage case. I am asking about simple DI usage without AOP involved.
Same question for Guice!

Spring uses proxies every time you use annotations like #Transactional or #Cacheable. It's AOP has nothing to do with the complex AOP that requires a post compile or weaving.
Anyway, be aware that if in one of your services you've autowired a repository, and inside the service you create a class where you set the repository, this will be automatically used as a proxy (if there's an annotation that requires it).
About Guice, the answer is in the comment of #Oliver.

In HK2 whether or not proxies are made for injection points depends on the scope/context of the bean being injected. In particular, in HK2 a scope can be annotated with Proxiable. You can control with the Proxiable annotation whether or not proxies should be generated for injections of beans into other beans of the same scope.
You can further control whether beans in non-proxiable scopes DO get proxied or beans in proxiable scopes should NOT be proxied with the annotations Unproxiable and UseProxy. There are equivalent verbs in the EDSL as well (for example ServiceBindingBuilder.proxyForSameScope).
In additions proxies would be generated by HK2 if AOP was in play

Assisted injection in Guice might be a use-case that could be of interest to you. Long story very short.
Factory interface:
public interface PaymentFactory {
public Payment create(Date startDate, Money amount);
}
Payment implementation:
public class RealPayment implements Payment {
#Inject
public RealPayment(
CreditService creditService,
AuthService authService,
#Assisted Date startDate,
#Assisted Money amount);
}
...
}
Binding:
install(new FactoryModuleBuilder()
.implement(Payment.class, RealPayment.class)
.build(PaymentFactory.class));
Guice will then generate the PaymentFactory implementation for you.
More details and the complete exapmple are available in the wiki. Note: this is a guice extension. I'm not aware of more Guice use cases except those mentioned by Olivier Grégoire in his comment.

Related

How does Java Spring #Autowired work with interface inheriting from several interfaces?

I have a Java Spring Framework project. After a bit of googling I found a way to include custom JPA methods into a JpaRepository. The injection of my repository into my service class using #Autowired works, but I can't understand how Spring handles the injection in this case. Could someone explain how Spring does the injection of CalendarEventRepository into CalendarEventService when the method implementations are in separate classes. It finds the JpaRepository implementation somewhere and my own custom implementation class with my custom method. Howcome their methods are accessible through the same reference variable calendarEventRepository? Bonus question: how does Spring find and instantiate the implementation for JpaRepository?
public interface CalendarEventRepository extends JpaRepository<CalendarEvent, Long>, CalendarEventRepositoryCustom { }
public interface CalendarEventRepositoryCustom {
public List<CalendarEvent> findCalendarEventsBySearchCriteria(CalendarEventSearchCriteria searchCriteria);
}
public class CalendarEventRepositoryImpl implements
CalendarEventRepositoryCustom {
public List<CalendarEvent> findCalendarEventsBySearchCriteria(CalendarEventSearchCriteria searchCriteria) {
}
}
public class CalendarEventService {
#Autowired
CalendarEventRepository calendarEventRepository;
...
calendarEventRepository.delete(calendarEvent);
...
return calendarEventRepository.findCalendarEventsBySearchCriteria(searchCriteria);
...
}
Thanks in advance!
When you are using Spring JPA repository interface (extend JpaRepository class), the important thing is that the implementation of the interface is generated at runtime. Method names are used by Spring to determine what the method should (since you have written the name findCalendarEventsBySearchCriteria correctly, it means that you already know that). In your particular case, CalendarEventRepository extends CalendarEventRepositoryCustom and therefore has a method findCalendarEventsBySearchCriteria(...), and also extends JpaRepository<CalendarEvent, Long>, which means that it should be treated as JPA repository, and the corresponding implementation should be generated.
To enable the generation of the repository implementation, you need to either include <jpa:repositories base-package="..." /> to your XML configuration file, or #Configuration #EnableJpaRepositories(basePackage = "...") When you have these, that's all the information Spring needs to generate (instantiate) repository and add it to application contexts, and the inject it into other beans. In your case, #Autowired CalendarEventRepository calendarEventRepository; specifies where it should be injected. I guess it more answers bonus question than the main one, but seems better to start with it.
I haven't yet touched CalendarEventRepositoryImpl. You should use such class if you want to drop the mentioned generation of repository implementation for particular methods. Spring looks for a class which name equals to repository interface's name + "Impl". If such class exists, Spring merges its methods with generated ones. So, see for yourself whether auto-generated findCalendarEventsBySearchCriteria method fits your needs or you want to implement it yourself. If the generated one fits, you should consider removing CalendarEventRepositoryImpl at all.
Could someone explain how Spring does the injection of
CalendarEventRepository into CalendarEventService when the method
implementations are in separate classes.
Answer: First, and most important - all Spring beans are managed - they "live" inside a container, called "application context".
Regardless of which type of configuration you are usin (Java or xml based) you enable "Component Scanning" this helps Spring determine which resource to inject.
How spring determines which bean to inject:
Matches the names.
Matches the type.
You even use Qualifiers to narrow down the search for spring.
It finds the JpaRepository implementation somewhere and my own
custom implementation class with my custom method. Howcome their
methods are accessible through the same reference variable
calendarEventRepository?
This is more of a java core question of inheritance. Since JpaRepository, CalendarEventRepositoryCustom and CalendarEventRepository are the base classes (implementations) of your CalendarEventRepositoryImpl so any method/field that is public or protected is available to CalendarEventRepositoryImpl class.
Here you are using "Program though interface" your reference variable here is calendarEventRepository which is an interface (parent) and that is why you are able to access the fields/methods.
Bonus question: how does Spring find and instantiate the
implementation for JpaRepository?
In spring configuration (java based) you tell spring to search for JPARepositories as below:
#EnableJpaRepositories(
basePackages = {
"com.package"}
, entityManagerFactoryRef = "EntityManagerFactory", transactionManagerRef = "jpaTransactionManager"
)
This is how spring gets to know which beans to create.
I recommend reading out Spring in Action (2nd to 4th Edition) by Craig Walls.
You can as well go through the https://spring.io/docs
Annotations (Autowired, Inject, your custom) works because of AOP. Read a bit about AOP and you will know how that works.

Can I inject dependencies into objects not created by the DI framework

How can I inject dependencies into objects that weren't created by a DI framework?
I am running an application on Google App Engine using Objectify, so POJOs are created by Objectify when data is fetched from the datastore. Personally i like having convenience methods to get related objects, like car.getOwner().getName() The car object is created by Objectify. The code of getOwner() owner would be something like
public Person getOwner(){
return PersonService.getById(this.ownerId);
}
I could improve it with a ServiceLocator
public Person getOwner(){
return ServiceLocator.getService(PersonService.class).getById(this.ownerId);
}
But how would I do this with DI?
I looked at Guice, but i can only think of putting the Injector in a singleton and access it from the getOwner method.
Is my thinking flawed?
If you are using Objectify4 you can subclass ObjectifyFactory and override the construct() method. This will allow you to inject your entity classes.
You can see an example here: https://github.com/stickfigure/motomapia/blob/master/java/com/motomapia/OfyFactory.java
The only solution I can think of is load time weaving, I quote:
The context:load-time-weaver registers AspectJ's Load-time Weaver to
the current classloader. So, not only Spring beans will be targeted,
but any class loaded in the classloader that match the defined
pointcuts.
But I think that will conflict with the GAE restrictions but I haven't tried this in GAE yet.

#Inject only working for POJOs created by CDI container?

I just want to confirm that I fully understood the prerequisites for CDI to work. If I have a class A:
public class A {
#Inject private B b;
}
Now when I instantiate this class using:
A a = new A();
In that case, A.b will be null.
But if I define in another class a member:
#Inject A a;
and later use a, a.b will be correctly populated?
Does CDI only work if the class requiring an injection was also created by CDI container? Or what am I missing if injections turn out to be null while creating a POJO using ordinary instantiation with new (yes, I got beans.xml in place)?
Does CDI only work if the class requiring an injection was also
created by CDI container?
Yes, that's pretty much it. The lifecycle of a ManagedBean is controlled by the container and should never be instantiated with the new keyword (BTW: the same is true for EJBs & Spring beans). If you need to create a new ManagedBean you will probably want to use a producer method.
While others have stated correctly that for the most part DI containers will not inject dependencies into bean that they did not instantiate this is not entirely true.
Spring has a wonderful feature that will autowire the bean when you create it using new A().
You just have to use AspectJ and mark your bean with the #Configurable annotation.
#Configurable
public class A {
#Inject private B b;
}
Its actually kind of an awesome feature cause you can do Active Record style POJO's while still honoring your DI (its in fact how Spring Roo does it).
You should also know that with Spring you can autowire a bean programmatically after its been instantiated with the AutowireCapableBeanFactory. This is how it typically autowires JUnit Test Case Classes because JUnit creates the test case classes.
Yes Spring is not CDI but in theory you could write your own #Configurable for CDI or there is probably a CDI way of doing the above.
That being said the above is sort of a sophisticated feature (and kind of a hack) and as #JanGroth mentioned understaning the lifecycle bean management of the container is critical whether its CDI, Spring, Guice etc.
You may use BeanProvider.injectFields(myObject); from Apache DeltaSpike.
Yes, #Inject works only inside a container because it is done using interceptors on method calls. When the container creates a bean it wrappes it in interceptors which perform injection, and in the case of instantiation using new no interceptors will be called during bean method invocation, and there will be no injection.
Here's the conditions needed for a class to be a managed bean (and hence, for the #Inject annotation to work on its fields/methods):
http://docs.oracle.com/javaee/6/tutorial/doc/gjfzi.html

Is there a standard way to enable JSR 303 Bean Validation using annotated method arguments

I've been looking a around for a while now with no luck. I'n not using Spring MVC but still want to use #javax.validation.Valid to enable validation of method arguments. To give an example
public class EventServiceImpl implements IEventService {
#Override
public void invite(#Valid Event event, #Valid User user) { ... }
}
Using MVC, this is enabled for #Controller annotated beans with a simple <mvc:annotation-driven/> (see 5.7.4.3 Configuring a JSR-303 Validator for use by Spring MVC).
Using AOP should be quite trivial. Nevertheless, I suspect there's some standard way to do this. Hence the question: Is there a similar thing for non-MVC applications and non-controller beans to enable input validation for annotated beans?
Method level validation is not part of the Bean Validation specification (JSR 303). Method level validation is a suggestion in the spec added in appendix C.
Hibernate Validator 4.2 (a beta is out already) is implementing this suggestion and allows to place JSR 303 annotations on method parameters and return values. Of course you will still need some Spring glue code, but that should not be too hard.
Also Bean Validation 1.1 will add method level validation officially to the spec (not just as appendix/recommendation). See also http://beanvalidation.org/
Using MVC, this is enabled for #Controller annotated beans
#Valid is just a marker in Controller beans that hides the code that does the validation and puts all constraint violations in Errors in a nice way. Spring designers could have invented their own annotation to do the same thing.
The real use of #Valid annotation is in the class (bean) that you are validating with JSR 303 validator and its primary use is to validate the object graph. Meaning one bean can have other
bean references with #Valid annotation to trigger validation recursively.
Outside the MVC, you can use configured validator to validate any bean that uses JSR 303 annotations but, unlike the nicely populated Errors in controller, you will have to decide yourself what you are going to do with constraint violations.
So, to answer your question, there is no standard way. To have the same appearance as in a controller, you could use #Valid annotation (or create a new one) to run AOP advice to validate a bean and populate a 'ViolationCollector' (something like Errors in MVC) that must be passed to a method.
The answers seem to be quite old. As of now, you can utilize #Validated and MethodValidationPostProcessor for method inline validation of any Spring beans. They are basically responsible for creating pointcut-like behavior for Spring managed beans of any tier, not Controllers specifically.
Also see my other answer.

Whats the best way to inject same instance of service in service for Spring AOP

I'va a ServiceImpl with is annotated with #Service stereotype of Spring and have two methods in it each one is annotated with custom annotations which are intercepted by Spring.
#Service
public class ServiceImpl implements Service{
#CustomAnnotation
public void method1(){
...
}
#AnotherCustomAnnotation
public void method2(){
this.method1();
...
}
}
}
Now Spring uses proxy based AOP approach and hence as I'm using this.method1() interceptor for #CustomAnnotation will not able to intercept this call, We used to inject this service in another FactoryClass and in that way we were able to get the proxy instance like -
#AnotherCustomAnnotation
public void method2(){
someFactory.getService().method1();
...
}
I'm now using Spring 3.0.x, which is the best way to get the proxy instance?
The other alternative is to use AspectJ and #Configurable.
Spring seems to be going towards these days (favoring).
I would look into it if you are using Spring 3 as it is faster (performance) and more flexible than proxy based aop.
Both methods are inside the same proxy, whereas the AOP functionality just enriches calls from the outside (see Understanding AOP Proxies). There are three ways for you to deal with that restriction:
Change your design (that's what I would recommend)
Change proxy type from JDK-proxy to proxy-target-class (CGLib-based subclassing) Nope, that doesn't help, see #axtavt's comment, it would have to be static AspectJ compilation.
Use ((Service)AopContext.currentProxy()).method1() (Works, but is an awful violation of AOP, see the end of Understanding AOP Proxies)
You could make your ServiceImpl class implement the BeanFactoryAware interface, and lookup itself thanks to the provided bean factory. But this is not dependency injection anymore.
The best solution is to put method1 in another service bean, which would be injected in your existing service bean and to which your existing service bean would delegate.

Categories

Resources