我正在编写一个小型应用程序以检查spring-AOP中“ AfterAdvice”概念的功能,但是我遇到了与xml文件有关的异常(我认为),请帮助我如何解决该异常
applicationContext.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-4.0.xsd">
<bean id="pinCheck" class="com.nt.advice.AtmPinVerifierAdvice" />
<bean id="targetBean" class="com.nt.service.AtmPinGenerator" />
<bean id="pfb" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="targetBean" />
<property name="interceptorNames">
<list>
<value>pinCheck</value>
</list>
</property>
</bean>
</beans>
ClientApp.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.nt.service.AtmPinGenerator;
public class ClientApp {
public static void main(String[] args) {
//activate IOC container
ApplicationContext ctx = new FileSystemXmlApplicationContext("src/com/nt/cfgs/applicationContext.xml");
//get proxy obj
AtmPinGenerator gen = ctx.getBean("pfb",AtmPinGenerator.class);
//call b.method
gen.pinGenerator();
}
}
AtmPinGenerator.java
import java.util.Random;
public class AtmPinGenerator extends Random {
//generating pin
public int pinGenerator(){
//creat java.util.Random object
Random rad = new Random();
//use nextInt() to generate random pin of 4 digits
int pin = rad.nextInt(9999);
return pin;
}//pinGenerator
}
AtmPinVerifierAdvice.java
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class AtmPinVerifierAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object retValue, Method method, Object[] args,
Object target) throws Throwable {
System.out.println(retValue);
Integer pin = (Integer)retValue;
//if generated pin is less than four digit throw an exception
if(pin<=999)
throw new IllegalArgumentException("invalid pin");
}//afterReturning
}//AtmPinVerifierAdvice
如果我运行上述应用程序,我将收到此异常
输出量
Aug 17, 2015 2:03:57 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.FileSystemXmlApplicationContext@3ff14318: startup date [Mon Aug 17 14:03:57 IST 2015]; root of context hierarchy
Aug 17, 2015 2:03:57 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from file [G:\java\Frameworks\SpringAOP\AOPProj6(After advice - pin verifier decl)\src\com\nt\cfgs\applicationContext.xml]
Exception in thread "main" org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'pfb' must be of type [com.nt.service.AtmPinGenerator], but was actually of type [com.sun.proxy.$Proxy2]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(Abstract BeanFactory.java:375)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBe anFactory.java:199)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractA pplicationContext.java:962)
at test.ClientApp.main(ClientApp.java:14)
我不明白为什么会出现异常。请有人帮助我,为什么会引发这种例外情况?
最佳答案
默认情况下,Spring使用基于接口的JDK动态代理来应用AOP。
您的AtmPinGenerator
扩展了实现Random
的Serializable
。 Spring会看到该接口并使用基于接口的代理。您将获得仅实现Serializable
接口的代理。
您有3个解决方案
通过配置ProxyFactoryBean
强制基于类的代理
创建一个接口并实现它
通过不扩展Random
来强制基于类的代理。
最后一个选择是最简单的选择,就是不扩展Random
,这将强制使用基于类的代理。
public class AtmPinGenerator {
public int pinGenerator(){
Random rad = new Random();
return rad.nextInt(9999);
}
}
您还可以将
proxyTargetClass
的ProxyFactoryBean
属性设置为true
,然后无需更改类。<property name="proxyTargetClass" value="true" />
最后一个选择是引入一个接口,并简单地在其上公开
pinGenerator()
方法,并让您的AtmPinGenerator
实现该接口。public interface PinGenerator {
int pinGenerator();
}
public class AtmPinGenerator implements PinGenerator { ... }
这样,您将使用基于代理的接口。现在,在您的
main
方法中,使用PinGenerator
界面而不是AtmPinGenerator
。