2015-08-17 167 views
3

我正在寫一個小應用程序來檢查spring-AOP中的「AfterAdvice」概念的功能,但我得到一個與xml文件相關的異常(我認爲)請幫助我如何解決異常如何解決BeanNotOfRequiredTypeException

的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.[email protected]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

通過像這樣配置ProxyFactoryBean來強制使用基於類的代理。默認情況下,使用JDK代理,並且目前你得到的代理只實現了'Serializable'(它由'Random'實現)。要修復啓用基於類的代理或者打包另一個接口,例如包含您所需要的方法的PinGenerator,然後編程到該接口而不是具體類。 –

回答

2

默認情況下,Spring使用基於接口的JDK動態代理來應用AOP。

您的AtmPinGenerator延伸Random實施Serializable。 Spring看到這個接口並使用基於接口的代理。您將獲得僅實現Serializable界面的代理。

你有3個選擇通過配置ProxyFactoryBean

  • 創建的接口,並通過不延長Random實現基於它
  • 強制類代理去解決它

    基於
    1. 強制類代理。

    最後一個選項最簡單的就是不擴展Random,這會強制使用基於類的代理。

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

    您也可以在ProxyFactoryBeanproxyTargetClass屬性設置爲true然後你不需要改變你的類。

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

    的最後一個選項是引入一個接口,簡單地揭露它的pinGenerator()方法,讓你的AtmPinGenerator實現該接口。

    public interface PinGenerator { 
    
        int pinGenerator(); 
    } 
    
    public class AtmPinGenerator implements PinGenerator { ... } 
    

    這樣你使用的是基於接口的代理。在您的main方法現在使用PinGenerator接口而不是AtmPinGenerator

  • +0

    非常感謝M.Dinum您的解決方案非常棒我使用最後一種方法解決了我的問題。但我會嘗試用其餘的方法來解決我的問題,而不需要修改類。謝謝 –