Can someone explain ProxyFactoryBean in simple terms?
I see this being quoted lot of places.
ProxyFactoryBean is used to apply interceptor logic to an existing target bean, so that when methods on that bean are invoked, the interceptors are executed before-and-after that method call. This is an example of Aspect Oriented Programming (AOP).
This is best explained using a simple example. A classic use-case for AOP is to apply caching to the result of a method call. This could be wired up using ProxyFactoryBean as follows:
<bean id="targetService" class="com.x.MyClass"/>
<bean id="cachingInterceptor" class="com.x.MyCachingInterceptor"/>
<bean id="cachedService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="targetService"/>
<property name="interfaces">
<list>
<value>com.x.MyService</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>cachingInterceptor</value>
</list>
</property>
</bean>
We have a bean targetService of type com.x.MyClass, which implements the interface com.x.MyService. We also have a interceptor bean called cachingInterceptor, which implements the interface org.aopalliance.intercept.MethodInterceptor.
This config will generate a new bean, called cachedService, which implements the MyService interface. Any calls to the methods on that object will first be passed through the cachingInterceptor object's invoke() method, which in this case would look for the results of previous method calls in its internal cache. It would either return the cached result, or allow the method call to proceed to the appropropriate method on targetService.
targetService itself knows nothing of this, it's completely unaware of all this AOP stuff going on.
ProxyFactoryBean is heavily used internally within Spring to generate proxies for a variety of reasons (e.g. remoting stubs, transaction management), but it's perfectly suitable for use in application logic also.
The ProxyFactoryBean applies aspects to an existing bean. You start out with your existing bean (the target bean), which spring "wraps" to add the aspects you provide. The returned bean has the same interface as your original bean, but with the additional aspects weaved around the target bean's methods.
Related
Information part:
Application uses spring context.xml for declaring spring beans.
I need inject prototype bean into singleton every time of prototype using (sounds trivial). This part has is clear for me on flow & implementation side.
Example of declaring bean is:
<bean id="entryNumberHelper" class="path.toMyBean.EntryNumberHelper"
lazy-init="true" scope="prototype">
<constructor-arg name="orderEntryGroup" value="dynamicValueNewForDifferentPrototypes"/>
<property name="modelService" ref="modelService"/>
</bean>
Questions:
How to describe in xml creation of parameterized prototype (only singleton where prototype should be injected knows about orderEntryGroup parameter)?
How to inject one in dynamic way?
P.S. - workaround
I can create one more method that can be used for prototype building (creation and tuning) but I dislike redundant code and hoping for elegant solution hidden in spring framework.
I try to implement solution for Generic DAO like this https://stackoverflow.com/a/511417.
However for “Using this genericDAO without special implementation Class” case I get the NoSuchBeanDefinitionException.
The full stacktrace http://pastebin.com/HwrjEZiX
As I see Spring can't wiring bean for Generic Dao without special implementation class
https://dl.dropboxusercontent.com/u/8384811/Misc/2013-05-14_224944.jpg
Spring uses the JdkDynamicAopProxy for wiring BranchHibernateDao class, “Using this genericDAO with special implementation Class” case.
According JavaDoc it Creates a dynamic proxy, implementing the interfaces exposed by
* the AopProxy. Dynamic proxies cannot be used to proxy methods
defined in classes, rather than interfaces.
So it sees the methods from BrunchDao and Crud interfaces for branchDao bean definition.
However it can't wire the branchGenericDao (“Using this genericDAO without special implementation Class” case) and don't see the Crud interface methods.
I'll appreciate for any help!
Bean's wiring
<bean id="branchDao" class="org.jtalks.poulpe.model.dao.hibernate.BranchHibernateDao" parent="genericDao"/>
<bean id="branchGenericDao" class="org.jtalks.common.model.dao.hibernate.GenericDao">
<qualifier value="branchGenericDao"/>
<constructor-arg name="sessionFactory" ref="sessionFactory"/>
<constructor-arg name="type" value="org.jtalks.poulpe.model.entity.PoulpeBranch"/>
</bean>
<bean id="genericDao" abstract="true" class="org.jtalks.common.model.dao.hibernate.GenericDao">
<constructor-arg name="sessionFactory" ref="sessionFactory"/>
</bean>
Test source is here https://github.com/jtalks-org/poulpe/blob/master.senleft/poulpe-model/src/test/java/org/jtalks/poulpe/model/dao/hibernate/BranchHibernateDaoTest.java
Crud source is here https://github.com/jtalks-org/jtalks-common/blob/master.senleft/jtalks-common-model/src/main/java/org/jtalks/common/model/dao/Crud.java
GenericDao source is here https://github.com/jtalks-org/jtalks-common/blob/master.senleft/jtalks-common-model/src/main/java/org/jtalks/common/model/dao/hibernate/GenericDao.java
BranchHibernateDao source is here https://github.com/jtalks-org/poulpe/blob/master.senleft/poulpe-model/src/main/java/org/jtalks/poulpe/model/dao/hibernate/BranchHibernateDao.java
The problem is probably with your test. When you write tests with Spring, you have to use the proper Spring test runner. Try modifying your test to work more like this, or try actually implementing it and not doing it with a testing framework to see if it works.
Also, if you want to create generic daos and you're using Hibernate, you should REALLY look into Spring Data JPA. Using it will make your life 10x easier than doing what you're trying to do, since it does what you're trying to do, but with less work and better options than you'll be able to implement by yourself.
(The answer you're following pre-dates Spring Data. I'm sure they would've used Spring Data if it existed.)
I have a static method I have no control over: MyUtils.getServiceURL() which returns a URL. I need to extract just the port from this URL to set a property on a bean:
<bean id="myBean>
<property name="defaultPort" value="?????"/>
</bean>
I can get the string value of the URL as a bean like this:
<bean id="serviceURL" class="MyUtils" factory-method="getServiceURL" />
I'm probably just going to write a method to parse the URL in myBean and extract the port. I was wondering if there was a way to avoid having to do this, and configure this directly in the spring context?
No need for custom classes, or parsers. Remember, a bean is just a class with get/is/set methods. A java.net.URL class qualifies as such.
Solution: Use a java.net.URL as a Spring-configurable bean and call it's getPort method.
Remember, in Spring, you can wire anything as a bean very easily so long as it sports methods using the get/is/set Bean convention. The java.net.URL class does such a thing.
** warning ** I'm just typing this out of my a$$, you'll have to check for any syntax shenanigans that I might be introducing in this Spring-config pseudo-code. One thing that is certain is that the concept will work with Spring 2.5 and that it relies on the util schema.
If you are using an older version of Spring, you'll have to use a PropertyPathFactoryBean. If you are using Spring 3.0, you'll want to use Spring expression language (EL), but I can't comment on the later since I'm not familiar with Spring 3.0.
In java:
int port = (new URL(MyUtils.getServiceURL()).getPort()
In Spring:
<bean id="serviceURL" class="MyUtils" factory-method="getServiceURL" />
<bean id="myURL" class="java.net.URL">
<constructor-arg>
<ref-bean="serviceURL"/>
</constructor-arg>
</bean>
<util:property-path id="defaultPort" path="myURL.port"/>
<bean id="myBean>
<property name="defaultPort" ref="defaultPort"/>
</bean>
There might be a way to consolidate all these four expressions into three or less, don't know if that will improve readability, though. The concept remains the same, though. Treat a java.net.URL instance as a bean, set its URL via its constructor, and get a hold (via Spring) of its getPort() method.
** edit **:
If you are using Spring 2.5 you can create an inline groovy bean that does all that for you. I've seen people doing that as integration glue to get rid of multitude of temp Spring bean place holders. That's the best choice IMO when you need to define a class (when it's simpler than just using Spring tags) and when you know such a class won't be used outside of Spring wiring of things.
Not I can think of. Either way, you probably have to write something to parse the port out. Since you have no control of that static method, perhaps you may want to utilize the adapter pattern to hide that static method. Doing so also makes your code easier to test because you can easily mock that external API out. For example:-
public interface URLServiceAdapter {
int getServiceURLPort();
}
public class URLServiceAdapterImpl implements URLServiceAdapter {
public int getServiceURLPort() {
return MyUtils.getServiceURL().getPort();
}
}
Your beans will then rely on your adapter class instead of MyUtils.getServiceURL() directly:-
<bean id="urlServiceAdapter" class="project.URLServiceAdapterImpl" />
That way, you can do something like this:-
#Autowired
private UrlServiceAdapter urlServiceAdapter;
...
bean.setDefaultPort(urlServiceAdapter.getServiceURLPort());
SpEL is your friend.
<bean id="myBean>
<property name="defaultPort"
value='#{ T(com.foo.MyUtils).getServiceURL().split(":")[2].split("/")[0] }'/>
</bean>
Enjoy,
I am exposing a bean that is not thread safe via Spring's http invoker. What I want is that every remote call should get a new instance of the bean. I started by setting the scope to prototype for the bean that I am exposing in the Dispatcher servlet XML. But it still seemed to create only one instance. So all client threads were concurrently accessing the same bean instance.
Next I also set the scopr to prototype for HttpInvokerProxyFactoryBean in the client spring-config.xml. But even then I see a single instance of the bean being returned.
Any ideas on what I am doing wrong? Or has anyone else faced this problem.
Thanks in advance.
Here are the relevant snippets
DispatcherServlet-servlet.xml
<bean id="fuBeanImpl" class="com.fubar.FuBeanImpl" scope="prototype">
</bean>
<bean id="fuBeanService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
<property name="service" ref="fuBeanImpl"/>
<property name="serviceInterface" value="com.fubar.FuBean"/>
</bean>
spring-config.xml
<bean id="fuBeanService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean" scope="prototype">
<property name="serviceUrl">
<value>http://fubar/fuBeanService</value>
</property>
<property name="serviceInterface">
<value>com.fubar.FuBean</value>
</property>
<property name="httpInvokerRequestExecutor">
<bean class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor"/>
</property>
</bean>
There is another current question Prototype Scope not working about an almost identical problem.
Both of these solutions should work here also:
Tight coupling to the
ApplicationContext and looking up the
Bean manually
Lookup Method Injection via
CGLib (by yours truly)
This is because your HttpInvokerServiceExporter bean is still a singleton, and it has a reference to the prototype-scoped fuBeanImpl bean. So the exporter gets a single instance of FuBeanImpl and never asks for a new one. This is the problem with singleton-scoped beans referring to on-singleton-scoped beans - the reference "collapses" the prototype, effectively.
You need to make HttpInvokerServiceExporter a prototype-scoped bean also, although this might have side-effects. For example, you haven't told us what is referring to the HttpInvokerServiceExporter - probably a url-mapping definition somewhere?
edit: Since you've clarified that you're using a SimpleUrlhandlerMapping, then what you can do is to inject that with the name of the handler bean, rather than a direct bean reference to it. This means that the handler bean (i.e. the fuBeanService bean) can be a prototype, even though the SimpleUrlhandlerMapping is a singleton.
I have two Spring proxies set up:
<bean id="simpleBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref local="simpleBeanTarget"/>
</property>
<property name="interceptorNames">
<list>
<value>cacheInterceptor</value>
</list>
</property>
</bean>
<bean id="springDao" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="springDaoTarget"/>
<property name="interceptorNames">
<list>
<value>daoInterceptor</value>
</list>
</property>
</bean>
simpleBean works just fine -- springDao does not.
The SpringDao class looks like:
public class SpringDao extends JdbcDaoSupport {
private SimpleJdbcTemplate simpleJdbcTemplate;
public SimpleJdbcTemplate getSimpleJdbcTemplate() {
if (simpleJdbcTemplate==null) {
simpleJdbcTemplate= new SimpleJdbcTemplate(getDataSource());
}
return simpleJdbcTemplate;
}
...
And I have my unit test autowired like this:
#Autowired
#Qualifier("springDao")
protected SpringDao springDao;
And the first indication something is wrong is I get this error:
Could not autowire field: . . . nested
exception is
java.lang.IllegalArgumentException
If I comment out the #Qualifier annotation and run my unit test again, I get this:
No unique bean of type ... expected
single matching bean but found 2:
[springDaoTarget, springDao]
That is what I expected.
So I changed my autowiring to
#Autowired
#Qualifier("springDaoTarget")
protected SpringCustomerCapacityDao springDao;
And added the following to my unit test:
Object proxy = applicationContext.getBean("springDao");
Assert.assertNotNull(proxy);
Assert.assertTrue(proxy instanceof SpringDao);
And the instanceof test failed, which (to me) means that my proxy is not really my proxy.
So I'm confused. What's going on? How can I fix this?
Edit Here is the requested springDaoTarget definition, which will disappoint many people:
<bean id="springDaoTarget" class="com.company.SpringDao">
If the target of your proxy implements at least one interface then Spring's default behavior is to create a JDK Proxy that implements all the interfaces of the target. This means it will not be a subclass of the target class. You can override this by forcing the creation of CGLIB proxies instead which are dynamic subclasses of the target.
As a general rule, if you are going to use AOP but only use interfaces in a limited fashion you'll want to force CGLIB. Otherwise you will have lots of JDK Proxies in your container which are not of the same type as the bean implementations you loaded.
See Cliff Meyers blog: Spring AOP: CGLIB or JDK Dynamic Proxies?
It was easy to fix, once I figured it out. SpringDao no longer inherits from JdbcDaoSupport and now it works.