在编织没有接口和非公共方法的类时理解Spring AOP的问题

时间:2013-11-30 05:23:30

标签: java spring aop spring-aop

我正在学习Spring AOP,我创建了一个简单的项目,以了解它是如何工作的。请在下面找到我项目的主要部分:

我的Spring-Customer.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    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/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

    <aop:aspectj-autoproxy />



    <bean id="customerBoNoIterface" class="com.core.CustomerBoNoIterface" />


    <!-- Aspect -->
    <bean id="logAspect" class="com.aspect.LoggingAspect" />

</beans>

请在下面找到我的AOP切入点:

@Before("execution(* com.core.CustomerBoNoIterface.addCustmer*(..))")
    public void logBeforeDummy(JoinPoint joinPoint) {

        System.out.println("hijacked : " + joinPoint.getSignature().getName());
        System.out.println("******");
    }

请在下面找到我的班级CustomerBoNoIterface:

   public class CustomerBoNoIterface {

    private void addCustmerPrivate() {
        System.out.println("calling addCustmerPrivate()");
    }

    public void addCustmerPublic() {

        System.out.println("calling addCustmerPublic()");

    }

    protected void addCustmerProtected() {

        System.out.println("calling addCustmerProtected()");

    }

    void addCustmerDefault() {

        System.out.println("calling addCustmerDefault()");

    }



    public String addCustmerReturnString() {

        System.out.println("calling addCustmerPublic return string");
        return "";

    }

}

最后我的主要方法:

public class App {
    public static void main(String[] args) throws Exception {

        ApplicationContext appContext = new ClassPathXmlApplicationContext("Spring-Customer.xml");

        CustomerBoNoIterface customerBoNoIterfaceBean =appContext.getBean("customerBoNoIterface", CustomerBoNoIterface.class);
        customerBoNoIterfaceBean.addCustmerPublic();
        customerBoNoIterfaceBean.addCustmerDefault();
        customerBoNoIterfaceBean.addCustmerProtected();
        customerBoNoIterfaceBean.addCustmerReturnString();



    }

根据在线参考Spring AOP是由代理完成的,一个类需要实现一个接口才能使Spring能够编织方面,而且Spring只会将方面编织到公共方法中。

但是在我的情况下,我有一个没有接口的类,如上例所示,我能够在以下方法中应用AOP:

            customerBoNoIterfaceBean.addCustmerPublic();
        customerBoNoIterfaceBean.addCustmerDefault();
        customerBoNoIterfaceBean.addCustmerProtected();
        customerBoNoIterfaceBean.addCustmerReturnString();

所以当我运行Main方法时,我在eclipse的控制台中得到以下输出:

hijacked : addCustmerPublic
******
calling addCustmerPublic()
hijacked : addCustmerDefault
******
calling addCustmerDefault()
hijacked : addCustmerProtected
******
calling addCustmerProtected()
hijacked : addCustmerReturnString
******
calling addCustmerPublic return string

所以我无法理解Spring如何在public以外的方法中编织方面,以及没有接口的类?

提前致谢,

2 个答案:

答案 0 :(得分:2)

当使用方法时,Spring AOP使用反射API处理每个带注释的类,不会直接调用类的方法。因此,您建议的方法的可见性在这里并不重要。

Spring AOP提供两种代理 1)JDK代理:如果你的类实现了至少一个接口,这个代理将进入图片。

2)CGLIB代理:当你的类没有实现任何接口时,这个代理就会出现。

在您的情况下,您的类不实现任何接口,因此您的类将使用CGLIB代理进行代理。

答案 1 :(得分:1)

从春天doku切出:

  

Spring AOP默认使用AOP代理的标准J2SE动态代理。这样可以代理任何接口(或接口集)。

     

Spring AOP也可以使用CGLIB代理。这是代理类而不是接口所必需的。如果业务对象未实现接口,则默认使用CGLIB。由于编程接口而不是类是一种好的做法,业务类通常会实现一个或多个业务接口。在那些需要建议未在接口上声明的方法或者需要将代理对象作为具体类型传递给方法的情况下,可以强制使用CGLIB(希望很少见)。 / p>

请阅读Spring-Documentation,这绝对是非常棒的。 http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/

总结一下:您不需要实现一个接口只是为了使AOP成为可能。如果您没有实现接口,则会直接根据类生成CGLIB代理。我实际上经常使用它。您需要在类路径上考虑cglib:http://mvnrepository.com/artifact/cglib/cglib/3.0

修改的 关于我个人偏好的更多信息(很多人可能不同意)。最近,我已经不再为所有事情编写接口了。现在我只在必要时使用它们(例如我有2个实现,比如测试),它真正加快了我的工作并简化了我的代码。使用具有文本替换功能的现代IDE等等,如果你真的需要它,那么它很难提取界面(对我来说非常罕见)。这只是我个人的意见。