Java 具有Spring AOP的BeanNotOfRequiredTypeException

Java 具有Spring AOP的BeanNotOfRequiredTypeException,java,spring,spring-aop,Java,Spring,Spring Aop,我正在spring aop和spring配置文件下面进行尝试: <?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:context="http://www.springframework.org/schema/

我正在spring aop和spring配置文件下面进行尝试:

<?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:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
        http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <bean id="eddie" class="com.springinaction.Instrumentalist">
        <property name="instrument" ref="violin"></property>
        <property name="song" value="Samarame"></property>

    </bean>


    <bean id="kenny" class="com.springinaction.Instrumentalist">
        <property name="song" value="SAMARAME "></property>
        <property name="instrument" ref="saxopone"></property>
    </bean>

    <bean id="hank" class="com.springinaction.OneManBand">
        <property name="instruments">
            <props>
                <prop key="GUITAR">STRUM STRUM STRUM</prop>
                <prop key="CYMBAL">CRASH CRASH CRASH CRASH</prop>
                <prop key="HARMONICA">HUM HUM HUM</prop>
            </props>
        </property>
    </bean>

    <bean id="guitar" class="com.springinaction.Guitar">
    </bean>

    <bean id="violin" class="com.springinaction.Violin">
    </bean>

    <bean id="tabala" class="com.springinaction.Tabala">
    </bean>

    <bean id="saxopone" class="com.springinaction.Saxophone">
    </bean>

    <bean id="audience" class="com.springinaction.Audience"></bean>

    <aop:config>

        <aop:aspect ref="audience">

            <aop:before pointcut="execution(* com.springinaction.Performer.perform(..))" method="takeSeats()"/>
        </aop:aspect>
    </aop:config>

</beans>

STRUM STRUM STRUM
撞车
哼哼哼哼
当我运行代码时,我得到一个错误消息:

线程“main”中出现异常 org.springframework.beans.factory.BeanNotOfRequiredTypeException: 名为“eddie”的Bean必须是 [com.springinaction.Instrumentalist], 但实际上是在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:348) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) 在 org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1008) 在 Main.Main(Main.java:12)

如果我在spring配置文件中注释
元素,它运行得非常好


为什么会发生这种情况?

默认情况下,Spring通过使用代理类应用AOP。动态创建代理类以实现许多接口。您向它传递一个“handler”对象,然后在对其调用任何这些接口方法时调用该对象。您可以阅读代理对象的Javadoc

在初始化应用程序上下文中的所有bean之后,Spring将执行任何必要的后处理。这包括应用AOP建议。Spring将用名为
eddie
的bean替换为代理对象,在上面的示例中,代理对象在将调用传递给原始对象之前调用另一个对象上的方法。每当您请求名为
eddie
的bean时,您将得到代理对象而不是真实对象

我找不到上面stacktrace底部提到的
Main
类的源代码,但我找到了其余大部分代码。无论如何,在
Main
类中,您似乎在做类似的事情

Instrumentalist eddie = (Instrumentalist) appContext.getBean("eddie", Instrumentalist.class);
Spring应用程序上下文的
getBean(String,Class)
方法将检查返回的bean是否属于指定的类,如果不是,则抛出异常。这就是上面例子中发生的情况。代理对象不是
Instrumentalist
的实例,而是它自己的名为
$Proxy4
的代理类的实例。(此代理类不能是
Instrumentalist
的子类,因为所有代理类都扩展了
java.lang.reflect.proxy

代理类将始终实现它们创建时使用的所有接口。Spring将注意到
Instrumentalist
实现了
Performer
,因此它创建的代理类也将实现
Performer
。您可以将上面的行替换为

Performer eddie = (Performer) appContext.getBean("eddie", Performer.class);

而且,如果您只需要在
eddie
上调用
perform()
方法,您的代码应该可以工作。

感谢Pourquoi Litytestdata提供的详细答案。。。似乎你对SpringIdol竞赛很了解:)我想我需要学习代理类。。。再次感谢您的澄清。。。