【问题标题】:Spring AOP creates extra beanSpring AOP 创建额外的 bean
【发布时间】:2011-11-01 14:48:06
【问题描述】:

我正在玩 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 对象。

知道为什么会这样吗?

谢谢。

【问题讨论】:

  • 我认为 spring 为它创建了这个 bean 和代理。动态代理类扩展了基类,因此它应该在其构造函数中调用 super()。您可以在 CModel 构造函数中打印堆栈跟踪以确保(类似于 new Exception().printStackTrace())。

标签: java spring aop spring-aop


【解决方案1】:

虽然我不确定,但我的猜测是spring首先实例化了常规类,然后制作了一个CGLIB代理,它是一个子类。请注意,初始化时应使用@PostConstruct,保证使用一次。

为了验证我的假设,在构造函数中添加一个断点并查看它何时被调用 - 其中一次应该是在 CModel$EnhancedByCGLIB 之后

【讨论】:

  • 我认为你是对的。我实际上在博客上写了recently,也许 OP 会在那里找到更多细节。顺便说一句,还有更简单的方法来验证这一点:System.out.println(this) - 第二个打印行将产生类似CModel$EnhancedByCGLIB 的内容。
【解决方案2】:

当 Spring 为您的类创建代理时,它将使用 CGLIB 生成一个子类 CModel 的类。最终影响是您的构造函数将被调用两次。

查看 Spring 文档以获取更多详细信息(特别是第三个项目符号): http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-proxying

附带说明,如果您的类实现了接口,Spring 将使用 JDK 代理机制——而 JDK 代理机制不会调用您的构造函数。

【讨论】:

  • 该死 - 看起来我被打败了 :) 抱歉重复的答案。
猜你喜欢
  • 2014-06-17
  • 2020-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多