What happens behind the scene when We Proxy a object. Say for example i say that a bean id = "bookService" refers to the class TransactionProxyFactoryBean of Spring.
The target attribute of the TransactionProxyFactoryBean points to BookServiceImpl class. So BookServiceImpl (Which is an implementation of the interface BookService) is getting proxied.
But what happens here? Does this TransactionProxyFacotoryBean Class extends the target that is getting proxied?
If so, will the TransactionProxyFactoryBean subtype itself from the BookServiceImpl (implementation) or the BookService (Interface)?
The TransactionProxyFactoryBean will create a proxy. It won't itself be a proxy.
This proxy will handle the calls to your bean and, for the methods that you have configured to have transactions applied, will call the TransactionInterceptor which will start the transaction, call your bean's method, then end the transaction.
If you have proxyTargetClass="true" then the proxy will be a subtype of the class (using CGLIB). Otherwise the proxy will be a subtype of the interface that the target class implements.
Related
I am new to spring and trying to understand the framework. I have a class (say ClassA) which has execute() method. I am using "prototype" scope (#Scope) for this class.I am using #Async("customThreadPoolTaskExecutor) for this execute() method. I have already defined this customThreadPoolTaskExecutor in another class with #Configuration. Then I have another class (say ClassB) which uses BeanFactory of spring to get an object of ClassA using beanFactory.getBean(ClassA).
I am getting an error on this line inside ClassB
ClassA A = (ClassA) beanFactory.getBean(ClassA);
Error is as below
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'ClassA' is expected to be of type 'ClassA' but was actually of type 'jdk.proxy2.$Proxy103'
Note that above code works fine and returns an object of ClassA if I remove #Async from execute() method of ClassA.
I am looking to understand the root of the problem and clear some of my concepts about spring. What is the relationship between #Async and bean creation using BeanFactory's getBean method. Why does it work without #Async but not with #Async.
Note : The fix/workaround I have so far is to add "ScopedProxyMode" for ClassA as "TARGET_CLASS". After adding this to ClassA's #Scope annotation, things work ok but I am not able to understand the root cause of the issue.
I'm a bit confused about using method injection (lookup-method) and aop scoped-proxy (Since both used for different scoped beans injection) so
1) When to use method injection and when to use aop-scoped proxy ?
2) What is the reason why a aop-scoped proxy will not be used for a prototype bean ?
Both lookup method injection and scoped proxy are means to inject shorter lived beans into longer lived beans. However, they serve different use cases.
Method injection is useful in cases where a singleton-scoped bean has a dependency on a prototype-scoped bean.
A proxy gets injected in place of the desired bean and provides that bean depending on the context. For example, if a singleton bean (such as a Spring MVC controller) auto-wires a session scoped bean, then the proxy delivers that bean belonging to the current HTTP session.
Such a proxy doesn't apply well to a situation where a prototype bean shall be obtained at runtime. Lookup method injection is one way to obtain prototype instances at runtime.
However, method injection has limitations because it builds upon abstract methods. Hence, certain things like writing unit tests are more cumbersome, as you need to provide a stub implementation of the abstract method. Component scanning doesn't work with abstract classes either.
One alternative to method injection is Spring's ObjectFactory, or its JSR equivalent Provider.
Another, straightforward way of creating prototype bean instances at runtime (which even makes it possible to provide constructor arguments) is to implement a bean factory like the following:
#Configuration
public class MyProvider {
#Bean
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public MyThing create(String name) {
return new MyThing(name);
}
}
Usage:
#Component
public class MySingleton {
#Autowired
private MyProvider myProvider;
public void doStuffThatNeedsAPrototypeBeanInstance() {
MyThing thing = myProvider.create("some name");
...
}
}
For the question 1. When to use method injection and when to use aop-scoped proxy?
Let's say you have a singleton bean A has dependency on the prototype bean B. A has a method m which has B involved.
You got the object a of A and execute the method m several times. Every time m executing, a new object b of B needs to inject to a. That's the time you use the method injection.
Besides, if you have a singleton bean A has dependency on the session bean B. A has a method m which has B involved.
You got the object a of A and execute the method m several times. As long as the execution time is in a same session, a has the same object b of B. That's the time you use proxy.
From spring reference doc
Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the #Transactional annotation, as opposed to annotating interfaces. You certainly can place the #Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies. The fact that Java
annotations are not inherited from interfaces means that if you are using class-based proxies (proxy-target-class="true") or the weaving-based aspect (mode="aspectj"), then the transaction settings are not recognized by the proxying and weaving infrastructure, and the object will not be wrapped in a transactional proxy, which would be decidedly bad.
Though it only talks about interfaces, abstract classes are considered as non-concrete as well.
So if i have an abstract class
public abstract class BaseService{
//here is a concrete method
#Transactional
public void updateData{
//do stuff using dao layer
}
and a concrete class which extends the class
public class SpecialService extends BaseService{
//body of class
}
Now if i call specialService.updateData() from my controller class will it be transactional?
Granting that you have actually configured Spring transaction management correctly, using #Transactional on an abstract superclass will work, since #Transactional is itself annotated with #Inherited and from it's Javadoc we have:
Indicates that an annotation type is automatically inherited. If an
Inherited meta-annotation is present on an annotation type
declaration, and the user queries the annotation type on a class
declaration, and the class declaration has no annotation for this
type, then the class's superclass will automatically be queried for
the annotation type. This process will be repeated until an annotation
for this type is found, or the top of the class hierarchy (Object) is
reached. If no superclass has an annotation for this type, then the
query will indicate that the class in question has no such annotation.
Note that this meta-annotation type has no effect if the annotated
type is used to annotate anything other than a class. Note also that
this meta-annotation only causes annotations to be inherited from
superclasses; annotations on implemented interfaces have no effect.
To actually see that #Transactional is annotated with #Inherited check out it's Javadoc
I understand the how, but can't seem formally shape the definitions.
As known DI can be done via constructor or setter or interface.
I am confused about the latest one -interface based DI, is it used in Spring?
UPDATE: I gave bad examle in here, which led to wrong understanding.
To fix it up:
Say we have setter and in setter we inject interface implemented by some class. Is that considered DI via setter or interface?
http://martinfowler.com/articles/injection.html#UsingAServiceLocator
this article divides DI on:
"There are three main styles of dependency injection. The names I'm using for them are Constructor Injection, Setter Injection, and Interface Injection. If you read about this stuff in the current discussions about Inversion of Control you'll hear these referred to as type 1 IoC (interface injection), type 2 IoC (setter injection) and type 3 IoC (constructor injection). I find numeric names rather hard to remember, which is why I've used the names I have here."
Else Service Locator pattern used for IoC, is it the one that actually makes possible #Autowired? - ie that not all classes explicitly need to be declared in xml for DI, as we can declare them as #Repository or #Controller or alike again if I recall correctly.
Thanks,
Autowiring an interface means wire a bean implementing that interface. This relies on an implementation actually existing in the bean factory.
#Autowired
UserService us; // wire a bean implementing UserService
--
#Service
public class UserServiceImpl implements UserService {
// the #Service annotation causes this implementation of UserService to
// be made available for wiring in the bean factory.
}
Worth noting is that if you wire by interface, Spring will expect there to exist one and exactly one bean in the bean factory implementing that interface. If more than one bean is found, an error will be thrown and you will have to specify which bean to wire (using the #Qualifier annotation).
EDIT:
When wiring, you can either wire a member variable or a setter method.
#Autowired
UserService us;
--
#Autowired
public void setUserService(UserService us) {
this.us = us;
}
These two produce the same result. The difference is that in the former, Spring will use reflection to set the variable us to a bean implementing UserService. In the latter, Spring will invoke the setUserService method, passing the same UserService imlementation.
We have a legacy system where something like a Service Locator is used to instantiate and provide all service objects:
class ServiceLocator {
ServiceA serviceA;
ServiceB serviceB;
public ServiceLocator () {
serviceA = ...;
serviceB = ...;
}
public ServiceA getServiceA() {
return serviceA;
}
public ServiceB getServiceB() {
return serviceB;
}
}
(imagine 70 more fields and getters...)
This object is then passed around from class to class to provide access to the service objects.
It is outside the scope of the project to change this design for existing code, but to at least not make things worse, we would like to introduce Spring to progressively instantiate future services with DI similar to Introducing an IoC Container to Legacy Code.
In contrast to the aforementioned situation, we already know how we will access the spring created spring bean objects from our legacy code. Our problem are objects we plan to create with spring, that need any of the service objects created outside of the spring context.
We came up with the following solution:
Create a static accessor for the ServiceLocator and set it in the constructor, load the spring application context object. In the spring configuration create a bean for the ServiceLocator with the static accessor as described in Section 3.3.2.2 in the Spring reference:
<bean id="serviceLocator"
class="ServiceLocator"
factory-method="getInstance"/>
for each Service create another bean using "instance factory method" as described in Section 3.3.2.3:
<bean id="serviceA"
factory-bean="serviceLocator"
factory-method="getServiceA"/>
Create other beans referencing these "dummy beans".
I guess this would work, but creates a lot of seamingly unnessessary pseudo configuration. What I'd rather like is something like this:
"If a bean is referenced and that bean is not explicitly defined, search for a method with the needed signature and name in the ServiceLocator class and use this object."
Is it possible to do so? Are there any entry points into the spring bean instantiation process that I am not aware of and that can be used here? Can I do this by subclassing the spring application context class?
Any help would be greatly appreciated!
You can define a BeanFactoryPostProcessor to populate your application context with beans from ServiceLocator.
In BeanFactoryPostProcessor, use beanFactory.registerSingleton(...) to add a fully instantiated bean, or ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition(...) to add a definition (note that some application contexts may not implement BeanDefinitionRegistry, though all typical contexts implement it).