I have a bean definition in Spring and it’s proxy counterpart which is meant to be used everywhere:
<bean name="my.Bean" class="org.springframework.aop.framework.ProxyFactoryBean" scope="prototype"> <property name="proxyInterfaces" value="my.Interface"/> <property name="target" ref="my.BeanTarget"/> <property name="interceptorNames"> <list> <value>someInterceptor</value> </list> </property> </bean> <bean name="my.BeanTarget" class="my.InterfaceImpl" scope="prototype"> <property name="foo" ref="bar"/> </bean>
This all works well; and in pre-Spring v3 world I was using it like
ApplicationContext ctx = ...; my.Interface foo = (my.Interface) ctx.getBean("my.Bean"); // cast is necessary
In Spring 3 it became possible to do type safe lookups, e.g.:
my.Interface foo = ctx.getBean(my.Interface.class);
Again, this works well for ordinary beans whereas for proxied beans I am getting
my.BeanTarget instead of
my.Bean. I have tried to inline
my.BeanTarget (as shown in Spring documentation) to make it hidden, but all I got was
org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [my.Interface] is defined: expected single bean but found 0:
So is it possible to use type safe bean lookups with proxied beans and if yes – how?
The problem here is the
scope="prototype" on your
The context will only eagerly-initialize singleton bean definitions. Beans of non-singleton scope are only initialized when asked for. This means that when you ask the context for beans of a given type, the context cannot initialize those non-singleton beans in order to ask them for their type, it has to go purely on the information in the bean definition.
In the case of
ProxyFactoryBean, the type of the generated proxy is determined by complex logic that requires the bean to be fully initialized. Without that initialization,
ProxyFactoryBean can only report the target type as
I can’t say a way around this, other than using a singleton bean definition, or explicitly asking for the bean by name, e.g.
<bean id="my.Interface"> class="ProxyFactoryBean"... >
Here, we use the convention of bean names being the interface they implement.
It looks like the scope of proxies created by
ProxyFactoryBean should be specified using
singleton property instead of
<bean name="my.Bean" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="singleton" value="false"/> ... </bean>
This solved the problem when target bean is inner.
When you have several top-level beans of the same class, you can use a type-safe lookup by id:
my.Interface foo = ctx.getBean("my.Bean", my.Interface.class);
Can’t you make
my.Interface foo = ctx.getBean(my.Bean.class); ?
As Spring works with Interfaces, in the context of aop, you could define different set of interfaces and request the one you expect. This way no cast will be needed to a real class but Spring will manage interfaces.
Let’s say you have Class A implements B. You want to cast A to B but it is refused as A is a proxy due to aop.
Then make A implements C and C extends B. C owns needed methods, and C is private interface accessed only from your implementation code.
Finally ask spring to inject either B or C depending on your expectations.
PrivateItf executor = context.getBean(PrivateItf.class);
This way, even if real class is a proxy, it implements your Private Interface with all what your need.