BeanNotOfRequiredTypeException with Spring AOP

为君一笑 提交于 2019-12-21 05:38:08

问题


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?


回答1:


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.



来源:https://stackoverflow.com/questions/3590512/beannotofrequiredtypeexception-with-spring-aop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!