BeanNotOfRequiredTypeException с Spring AOP - PullRequest
       0

BeanNotOfRequiredTypeException с Spring AOP

3 голосов
/ 28 августа 2010

Я пробую свои силы в 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: bean-компонент с именем 'eddie' должен иметь тип [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.contextAppat com.springinaction.Main.main (Main.java:12)

Если я прокомментирую <aop:config> элемент в весеннем конфигурационном файле, он работает отлично ..

Почему это так?происходит?

1 Ответ

7 голосов
/ 28 августа 2010

По умолчанию Spring применяет AOP с помощью прокси-классов .Прокси-класс создается динамически для реализации ряда интерфейсов.Вы передаете ему объект-обработчик, который он затем вызывает, когда к нему вызывается любой из этих методов интерфейса.Вы можете прочитать Javadoc для прокси-объектов здесь .

После инициализации всех bean-компонентов в контексте приложения Spring выполнит любую необходимую последующую обработку.Это включает в себя применение рекомендаций АОП.Spring заменит bean-компонент с именем eddie на прокси-объект, который в приведенном выше примере вызывает метод для другого объекта перед передачей вызова исходному объекту.Всякий раз, когда вы запрашиваете бин с именем eddie, вы получаете прокси-объект вместо реального объекта.

Я не мог найти источник для класса Main, упомянутого в нижней частивыше, но я нашел большую часть кода здесь .В любом случае, в классе Main кажется, что вы делаете что-то вроде

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

Метод getBean(String, Class) контекста приложения Spring проверит, что возвращаемый компонент соответствует указанному классу, и если неткинь исключение.Это то, что произошло в вашем примере выше.Прокси-объект не является экземпляром Instrumentalist, это экземпляр его собственного прокси-класса с именем $Proxy4.(Этот прокси-класс не может быть подклассом Instrumentalist, потому что все прокси-классы расширяются java.lang.reflect.Proxy).

Прокси-классы всегда реализуют все интерфейсы, с которыми они были созданы.Spring заметит, что Instrumentalist реализует Performer, поэтому созданный им прокси-класс также реализует Performer.Вы можете заменить вышеуказанную строку на

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

, и, если вам нужно только вызвать метод perform() для eddie, ваш код должен работать.

...