首页 文章

在Spring AOP中使用代理

提问于
浏览
21

我正在读一本关于在Spring AOP中启用AspectJ支持的书 .

以下是从该书中摘录的一段:

要在Spring IoC容器中启用AspectJ注释支持,您只需在bean配置文件中定义一个空的XML元素aop:aspectj-autoproxy . 然后,Spring将自动为您的AspectJ方面匹配的任何bean创建代理 . 对于接口不可用或未在应用程序设计中使用的情况,可以依靠CGLIB创建代理 . 要启用CGLIB,您需要在<aop:aspectj-autoproxy />中设置属性proxy-target-class = true .

我无法得到第二段 . '接口不可用'是什么意思 . 任何人都可以用一个例子说明这一点

4 回答

  • 20

    我发现了一个博客here,它清楚地解释了AOP,Caching和Transaction如何使用运行时代理类 .

    什么时候不编码接口(引自博客's section ' What if the bean class does not implement any interface? '): -

    默认情况下,如果您的bean没有实现接口,Spring会使用技术继承:在启动时,会创建一个新类 . 它继承自bean类并在子方法中添加行为 . 为了生成这样的代理,Spring使用了一个名为cglib的第三方库 .

  • 5

    Spring AOP使用JDK动态代理或CGLIB来创建目标对象的代理 .

    根据Spring文档,如果您的目标实现至少一个接口,将使用JDK动态代理 . 但是,如果目标对象未实现任何接口,则将创建CGLIB代理 .

    这是您可以强制创建CGLIB代理的方法(set proxy-target-class =“ true ”):

    <aop:config proxy-target-class="true">
        <!-- other beans defined here... -->
     </aop:config>
    

    使用AspectJ及其autopoxy支持时,您也可以强制使用CGLIB代理 . 这是 <aop:aspectj-autoproxy> 的使用位置,此处"proxy-target-class"必须设置为 true

    <aop:aspectj-autoproxy proxy-target-class="true"/>
    

    有关更多详细信息,请参阅Aspect Oriented Programming with Spring文档的代理机制部分 .

  • 6

    Spring更喜欢使用AOP接口,因为它可以使用JDK proxies .

    比方说我有一个接口 MyService

    public interface MyService {
        void doSomething();
    }
    

    并实施 MyServiceImpl

    @Service
    public class MyServiceImpl implements MyService {
        public void doSomething() {
            // does something!
        }
    }
    

    如果Spring发现您已为 MyService 配置了方面,它将创建一个实现 MyService 的JDK代理,然后将所有调用代理到您的 MyServiceImpl bean,并在适当的位置添加方面功能 .

    JDK代理通过实现与目标对象相同的接口并委托对它的调用来工作;如果没有可实现的接口,它们将无法工作 . 如果您没有上面的接口,Spring需要使用像CGLIB这样的字节代码库来在运行时动态创建包含方面功能的类 .

  • 27

    Spring AOP广泛使用代理作为以非侵入方式实现跨领域关注(a.k.a方面)的机制,该思想基本上是使用代理作为包装器来丰富原始行为,即添加事务功能 .

    为实现此目的,有两个选项,取决于原始对象是否实现接口 .

    在第一种情况下(原始对象实现至少一个接口),反射API的动态代理功能用于创建一个代理对象,该代理对象可以代替原始对象和代理的相同接口 .

    在第二种情况下(原始对象实现 NOT 实现任何接口),因此必须使用更精细的技巧,这就是CGLIB出现的时候 . 根据项目页面"CGLIB is used to extend Java classes and implements interfaces at runtime" . 因此,在这种情况下,技巧包括创建一个代理 EXTENDS 原始对象,因此可以使用它 .

相关问题