我正在编写一个小型应用程序以检查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扩展了实现RandomSerializable。 Spring会看到该接口并使用基于接口的代理。您将获得仅实现Serializable接口的代理。

您有3个解决方案


通过配置ProxyFactoryBean强制基于类的代理
创建一个接口并实现它
通过不扩展Random来强制基于类的代理。


最后一个选择是最简单的选择,就是不扩展Random,这将强制使用基于类的代理。

public class AtmPinGenerator {

    public int pinGenerator(){
        Random rad = new Random();
        return rad.nextInt(9999);
    }
}


您还可以将proxyTargetClassProxyFactoryBean属性设置为true,然后无需更改类。

<property name="proxyTargetClass" value="true" />


最后一个选择是引入一个接口,并简单地在其上公开pinGenerator()方法,并让您的AtmPinGenerator实现该接口。

public interface PinGenerator {

    int pinGenerator();
}

public class AtmPinGenerator implements PinGenerator { ... }


这样,您将使用基于代理的接口。现在,在您的main方法中,使用PinGenerator界面而不是AtmPinGenerator

07-26 03:48