Spring AOP создает дополнительный компонент

Я играю с Spring AOP.

Вот простой класс

public class CModel extends Car {
    private double torqueMeasure = 1;

    public CModel() {
        System.out.println(" C-Model constructor");        
    }
}

И конфигурация Spring такая

<aop:config>
    <aop:aspect ref="audit">
        <aop:before pointcut="execution(* com.test.main..*(..))" method="firstControl"/>
            ...
    </aop:aspect>
</aop:config>

Хорошо сейчас; когда я добавляю aop:config и перехватываю CModel, Spring дважды вызывает конструктор CModel. Это означает, что Spring создает 2 объекта CModel, верно?

Если я удалю конфигурацию AOP, Spring создаст только один объект CModel.

Любая идея, почему это так?

Спасибо.


person Lurtz    schedule 01.11.2011    source источник
comment
Я думаю, что spring создает этот bean-компонент и прокси для него. Динамический прокси-класс расширяет базовый класс, поэтому он должен вызывать super() в своем конструкторе. Вы можете распечатать трассировку стека в конструкторе CModel, чтобы убедиться в этом (что-то вроде new Exception().printStackTrace()).   -  person svaor    schedule 01.11.2011


Ответы (2)


Хотя я не уверен, я предполагаю, что spring сначала создает экземпляр обычного класса, а затем создает прокси-сервер CGLIB, который является подклассом. Обратите внимание, что для инициализации следует использовать @PostConstruct, который гарантированно будет использован один раз.

Чтобы проверить мою гипотезу, добавьте точку останова в конструктор и посмотрите, когда она вызывается — в одном из случаев она должна быть сразу после CModel$EnhancedByCGLIB something

person Bozho    schedule 01.11.2011
comment
Я думаю, вы правы. На самом деле я писал об этом в блоге недавно, возможно, ОП найдет некоторые дополнительные подробности там. Кстати, есть еще более простой способ проверить это: System.out.println(this) - вторая напечатанная строка даст что-то вроде CModel$EnhancedByCGLIB. - person Tomasz Nurkiewicz; 01.11.2011
comment
Это описано в 7.6. Механизмы проксирования - person axtavt; 01.11.2011

Когда Spring создает прокси для вашего класса, он будет использовать CGLIB для создания класса, являющегося подклассом CModel. Чистый эффект заключается в том, что ваш конструктор будет вызываться дважды.

Ознакомьтесь с документацией Spring для получения более подробной информации (в частности, третьего пункта): http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-proxying

В качестве примечания: Spring будет использовать механизм проксирования JDK, если ваш класс реализует интерфейс, и механизм проксирования JDK не будет вызывать ваш конструктор.

person wmkoch    schedule 01.11.2011
comment
Черт, похоже, меня избили до предела :) Извините за дублирующийся ответ. - person wmkoch; 01.11.2011