Spring Aop ProxyFactoryBean и ProxyFactory и ClassCastException
Когда я использую ProxyFactoryBean
чтобы получить прокси-объект, я получаю ClassCastException, но когда я использую ProxyFactory getProxy()
чтобы получить объект прокси, он работает правильно. Я использую Spring 4.x.
Определение двух бобов ,WaiterTest и продавец:
public class WaiterTest {
public void greetTo(String name){
System.out.println("waiter greet to " + name +"...");
}
public void serveTo(String name){
System.out.println("waiter serving " + name + "...");
}
}
public class Seller {
public void greetTo(String name){
System.out.println("seller greet to " +name + "...");
}
}
Определение совета:
public class GreetingBeforeAdvice implements MethodBeforeAdvice{
public void before(Method method, Object[] args, Object obj) throws Throwable{
System.out.println(obj.getClass().getName() + "." + method.getName());
String clientName =(String) args[0];
System.out.println("How are you! Mr." + clientName +".");
}
}
Определение советника:
public class GreetingAdvisor extends StaticMethodMatcherPointcutAdvisor {
public boolean matches(Method method, Class clazz) {
return "greetTo".equals(method.getName());
}
public ClassFilter getClassFilter() {
return new ClassFilter() {
public boolean matches(Class clazz) {
return WaiterTest.class.isAssignableFrom(clazz);
}
};
}
}
Тестовый класс :
public class TestGreetingBeforeAdvisor {
public static void main(String[] args) {
//method one: use by ProxyFactory
WaiterTest targetWaiterTest = new WaiterTest();
Seller targetSeller = new Seller();
GreetingBeforeAdvice advice = new GreetingBeforeAdvice();
GreetingAdvisor advisor = new GreetingAdvisor();
advisor.setAdvice(advice);
ProxyFactory pf = new ProxyFactory();
pf.setTarget(targetWaiterTest);
pf.addAdvisor(advisor);
pf.setOptimize(true);
WaiterTest proxy = (WaiterTest) pf.getProxy();
proxy.greetTo("John");
proxy.serveTo("Tom");
ProxyFactory pf1 = new ProxyFactory();
pf1.setTarget(targetSeller);
pf1.addAdvisor(advisor);
Seller seller = (Seller) pf1.getProxy();
seller.greetTo("John");
System.out.println("=============");
//method two:Spring xml,use ProxyFactoryBean
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
WaiterTest test = (WaiterTest) ctx.getBean("waiterTest");
test .greetTo("John");
test .serveTo("John");
}
}
beans.xml:
<bean id="waiterTarget" class="com.xxx.springaop.advisor.WaiterTest"/>
<bean id="sellerTarget" class="com.xxx.springaop.advisor.Seller"/>
<bean id="greetingAdvice1" class="com.xxx.springaop.advisor.GreetingBeforeAdvice"/>
<bean id="greetingAdvisor" class="com.xxx.springaop.advisor.GreetingAdvisor"
p:advice-ref="greetingAdvice1"/>
<bean id="parent" abstract="true" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="greetingAdvisor"
p:proxyTargetClass="true"/>
<bean id="waiterTest" parent="parent" p:target-ref="waiterTarget"/>
<bean id="seller" parent="parent" p:target-ref="sellerTarget"/>
результат:
com.xxx.springaop.advisor.WaiterTest.greetTo
How are you! Mr.John.
waiter greet to John...
waiter serving Tom...
seller greet to John...
=============
Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy12 cannot be cast to com.xxx.springaop.advisor.WaiterTest
at com.xxx.springaop.advisor.TestGreetingBeforeAdvisor.main(TestGreetingBeforeAdvisor.java:48)
Суммировать:
WaiterTest proxy = (WaiterTest) pf.getProxy(); //success
WaiterTest test = (WaiterTest) ctx.getBean("waiterTest");//fail,ClassCastException
Зачем?
1 ответ
Я бы сказал, что вы не настроили "целевой" объект в своем определении ProxyFactoryBean. Прокси не может быть создан, если у него нет цели.
Я не смог воспроизвести вашу проблему, но я провел некоторый рефакторинг вашего кода, и это прекрасно работает для меня. Может быть, это поможет вам, по крайней мере, в качестве отправной точки..
Waiter.java
public class Waiter {
public void greetTo(String name) {
System.out.println("waiter greet to " + name + "...");
}
public void serveTo(String name) {
System.out.println("waiter serving " + name + "...");
}
}
GreetingBeforeAdvice.java
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class GreetingBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object obj) throws Throwable {
String clientName = (String) args[0];
System.out.println("How are you! Mr." + clientName + ".");
}
}
GreetingAdvisor.java
import org.springframework.aop.ClassFilter;
import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
import java.lang.reflect.Method;
public class GreetingAdvisor extends StaticMethodMatcherPointcutAdvisor {
public boolean matches(Method method, Class clazz) {
return "greetTo".equals(method.getName());
}
public ClassFilter getClassFilter() {
return new ClassFilter() {
public boolean matches(Class clazz) {
return Waiter.class.isAssignableFrom(clazz);
}
};
}
}
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="waiter" class="Waiter"/>
<!-- Advisor Configuration -->
<bean id="greetingAdvice" class="GreetingBeforeAdvice"/>
<bean id="greetingAdvisor" class="GreetingAdvisor">
<property name="advice" ref="greetingAdvice"/>
</bean>
<bean id="waiterProxyFactory" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interceptorNames">
<list>
<value>greetingAdvisor</value>
</list>
</property>
<property name="target" ref="waiter"/>
</bean>
</beans>
и, наконец, App.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
final Waiter waiter = (Waiter) ctx.getBean("waiterProxyFactory");
waiter.greetTo("Koray Tugay");
waiter.serveTo("Koray Tugay");
}
}
Для меня вывод с использованием Spring 4.3.12 выглядит следующим образом:
How are you! Mr.Koray Tugay.
waiter greet to Koray Tugay...
waiter serving Koray Tugay...