Spring AOP 的 BeanNotOfRequiredTypeException

发布于 2024-09-16 12:01:47 字数 3170 浏览 2 评论 0原文

我正在尝试使用 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>

当我运行代码时,我收到错误消息:

线程“main”中出现异常 org.springframework.beans.factory.BeanNotOfRequiredTypeException: 名为“eddie”的 Bean 必须属于类型 [com.springinaction.Instrumentalist], 但实际上是 [$Proxy4] 类型 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) 在 com.springinaction.Main.main(Main.java:12)

如果我在 spring 配置文件中注释 元素,它会完美运行..

为什么会发生这种情况?

I am trying my hands at spring aop and below the spring config file:

<?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>

when i run the code i am getting error saying:

Exception in thread "main"
org.springframework.beans.factory.BeanNotOfRequiredTypeException:
Bean named 'eddie' must be of type
[com.springinaction.Instrumentalist],
but was actually of type [$Proxy4] at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:348)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at
org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1008)
at
com.springinaction.Main.main(Main.java:12)

If i comment <aop:config> element in spring config file it is running perfectly..

Why it is happening?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

盗心人 2024-09-23 12:01:47

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

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

我找不到上面堆栈跟踪底部提到的 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);

and,只要您只需要调用 eddie 上的 perform() 方法,您的代码就应该可以工作。

By default, Spring applies AOP by using proxy classes. A proxy class is created dynamically to implement a number of interfaces. You pass it a 'handler' object which it then calls when any of these interface methods are invoked on it. You can read the Javadoc for proxy objects here.

After all the beans in the application context have been initialised, Spring will then do any post-processing necessary. This includes applying AOP advice. Spring will replace the bean with name eddie with a proxy object that, in your example above, calls a method on another object before passing the call on to the original object. Whenever you ask for the bean with name eddie, you'll get the proxy object instead of the real object.

I couldn't find the source to the Main class mentioned at the bottom of the stacktrace above, but I did find most of the rest of the code here. Anyway, in the Main class, it seems you are doing something like

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

The getBean(String, Class) method of the Spring application context will check that the bean returned is of the class specified, and if not, throw an exception. This is what has happened in your example above. The proxy object isn't an instance of Instrumentalist, it's an instance of its own proxy class called $Proxy4. (This proxy class can't be a subclass of Instrumentalist because all proxy classes extend java.lang.reflect.Proxy).

Proxy classes will always implement all interfaces they were created with. Spring will notice that Instrumentalist implements Performer, so the proxy class it creates will also implement Performer. You could replace the above line with

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

and, provided you only need to call the perform() method on eddie, your code should work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文