我正在编写一个小应用程序来检查" AfterAdvice"的功能。 spring-AOP中的概念,但我得到一个与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)
我不知道为什么会遇到异常。请任何人帮助我为什么会出现这种异常?
答案 0 :(得分:2)
默认情况下,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
的{{1}}属性设置为ProxyFactoryBean
,然后您无需更改班级。
true
最后一个选项是引入一个接口,只需在其上公开<property name="proxyTargetClass" value="true" />
方法,让pinGenerator()
实现该接口。
AtmPinGenerator
这样您就可以使用基于接口的代理。在public interface PinGenerator {
int pinGenerator();
}
public class AtmPinGenerator implements PinGenerator { ... }
方法中,现在使用main
界面而不是PinGenerator
。