7

我正在使用 spring 通过 bean 创建对象。现在我尝试使用 aop 创建相同的对象,我得到 $Proxy cannot be cast to SaleRoom 异常。

以前的 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"
xmlns:aop="http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
xmlns:context="http://www.springframework.org/schema/context/spring-context-2.5.xsd"
xmlns:flow="http://www.springframework.org/schema/webflow-config/spring-webflow-config- 1.0.xsd"
xmlns:jm s="http://www.springframework.org/schema/jms/spring-jms-2.5.xsd"
xmlns:jee="http://www.springframework.org/schema/jee/spring-jee-2.5.xsd"
xmlns:lang="http://www.springframework.org/schema/lang/spring-lang-2.5.xsd"
xmlns:osgi="http://www.springframework.org/schema/osgi/spring-osgi.xsd"
xmlns:tx="http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
xmlns:util="http://www.springframework.org/schema/util/spring-util-2.5.xsd"
xmlns:p="http://www.springframework.org/schema/p"

xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd     http://www.springframework.org/schema/aop/spring-aop-2.5.xsd/spring-spring-aop-2.5.xsd-2.5.xsd
http://www.springframework.org/schema/context/spring-context-2.5.xsd     http://www.springframework.org/schema/context/spring-context-2.5.xsd/spring-spring-context-2.5.xsd-2.5.xsd
http://www.springframework.org/schema/webflow-config/spring-webflow-config-1.0.xsd     http://www.springframework.org/schema/webflow-config/spring-webflow-config-1.0.xsd/spring-spring-webflow-config-1.0.xsd-2.5.xsd
http://www.springframework.org/schema/jms/spring-jms-2.5.xsd     http://www.springframework.org/schema/jms/spring-jms-2.5.xsd/spring-spring-jms-2.5.xsd-2.5.xsd
http://www.springframework.org/schema/jee/spring-jee-2.5.xsd     http://www.springframework.org/schema/jee/spring-jee-2.5.xsd/spring-spring-jee-2.5.xsd-2.5.xsd
http://www.springframework.org/schema/lang/spring-lang-2.5.xsd     http://www.springframework.org/schema/lang/spring-lang-2.5.xsd/spring-spring-lang-2.5.xsd-2.5.xsd
http://www.springframework.org/schema/osgi/spring-osgi.xsd     http://www.springframework.org/schema/osgi/spring-osgi.xsd/spring-spring-osgi.xsd-2.5.xsd
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd     http://www.springframework.org/schema/tx/spring-tx-2.5.xsd/spring-spring-tx-2.5.xsd-2.5.xsd
http://www.springframework.org/schema/util/spring-util-2.5.xsd     http://www.springframework.org/schema/util/spring-util-2.5.xsd/spring-spring-util-2.5.xsd-2.5.xsd
">
<bean id="sale01" class="application.common.entities.BidRoom">
<property name="itemId" value="0001"/>
<property name="lifeTime" value="15"/>
</bean>
</beans>

我使用以下代码来创建销售:

    ApplicationContext context = new FileSystemXmlApplicationContext(SalesManager.getSalesSourceFile());
    SaleRoom saleRoom;
    List<String> salesNames = new LinkedList<String>();
    List<SaleRoom> allSales = new LinkedList<SaleRoom>();

    // Get all sales id's for beans
    NodeList salesNodeList = salesDoc.getElementsByTagName("bean");

    for (int i = 0; i < salesNodeList.getLength(); i++) {
        Node nNode = salesNodeList.item(i);
        salesNames.add(((Element) nNode).getAttribute("id").toString());
    }

    for (String saleName : salesNames) {
        if(saleName.contains("sale")) {
            saleRoom = (SaleRoom) context.getBean(saleName);
            allSales.add(saleRoom);
        }
    }

    return allSales;

这是新的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"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

    <aop:aspectj-autoproxy>
        <aop:include name="logSettersCalls"/>
    </aop:aspectj-autoproxy>
    <bean id="logSettersCalls" class="application.logging.aop.LogSettersCalls"/>

    <bean id="sale01" class="application.common.entities.BidRoom">
        <constructor-arg index="0" type="int" value="0001"/>
        <constructor-arg index="1" type="int" value="15"/>
    </bean>
</beans>

Aspect 日志记录类:

@Aspect
public class LogSettersCalls {
   @Pointcut("execution(void set*(*))")
    public void setMethod() {}

    @Before("setMethod()")
    public void logSetterCall(JoinPoint theJoinPoint) {
        String methodName = theJoinPoint.getSignature().getName();
        Object newValue = theJoinPoint.getArgs()[0];
        Object theObject = theJoinPoint.getTarget();
        System.out.println("The method " + methodName + " is called on object " 
                + theObject + " with the value " + newValue);
    }
}

我使用相同的代码通过 aop 创建 bean。我在线程“main”java.lang.ClassCastException 中得到异常:$Proxy11 无法转换为 application.common.entities.SaleRoom

抛出异常的行: saleRoom = (SaleRoom) context.getBean(saleName);

任何帮助将不胜感激。谢谢。

4

1 回答 1

42

您的 SaleRoom 类是否实现了某些接口?如果是,那么您应该在代码中使用接口而不是类:

ISaleRoom saleRoom = (ISaleRoom) context.getBean(saleName);

因为如果你的 bean 实现了一些接口,那么 Spring 默认会基于这个接口创建代理。

这是一篇关于 Spring 中代理创建的好文章。

如果要为目标类创建代理,也可以更改 Spring AOP 的代理机制。这在参考文档中有所描述。

于 2012-11-19T20:56:02.957 回答