1
votes

I am learning Spring AOP and i have created a simple project in order to understand how it works. Please find below the main part of my project:

My 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>

Please find below my AOP pointcut:

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

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

Please find below my class 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 "";

    }

}

And finally my Main method:

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();



    }

According to the on line reference Spring AOP is done by proxy and a class needs to implement an interface in order for Spring to be able to weave the aspect and also Spring will weave aspect to public method only.

However in my case i have a class with no interface as shown in the above example and i am able to apply AOP in following method:

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

So when i run the Main method i get the following output in my console in eclipse:

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

So I am not able to understand how Spring is able to weave aspect in methods other than public and also a class with no interface?

Thanks in advance,

2

2 Answers

3
votes

When wheaving the methods, Spring AOP process each annotated class by using reflection API, won't call the methods of your class directly. So the visibility of your advised methods doesn't matters here.

Spring AOP provides two kinds of proxys 1)JDK proxy: This proxy will come in to picture if your class implements at least one interface.

2)CGLIB proxy: This proxy will come into picture when your class does not implements any interface.

In your case, your class does not implements any interface so your class will be proxied by using CGLIB proxy.

2
votes

cut out from spring doku:

Spring AOP defaults to using standard J2SE dynamic proxies for AOP proxies. This enables any interface (or set of interfaces) to be proxied.

Spring AOP can also use CGLIB proxies. This is necessary to proxy classes, rather than interfaces. CGLIB is used by default if a business object does not implement an interface. As it is good practice to program to interfaces rather than classes, business classes normally will implement one or more business interfaces. It is possible to force the use of CGLIB, in those (hopefully rare) cases where you need to advise a method that is not declared on an interface, or where you need to pass a proxied object to a method as a concrete type.

Just read the Spring-Documentation, which is absolutely great. http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/

To sum up: You don't need to implement an interface just for making AOP possible. If you don't implement an interface, a CGLIB Proxy is generated, based on the class directly. I use that a lot actually. You do need to have cglib on your classpath thought: http://mvnrepository.com/artifact/cglib/cglib/3.0

edit some more information on my personal preference (a lot of people might disagree). In recent times i've moved away from writing interfaces for just everything. Now i only use them when really necessary (e.g. i have 2 implementations, like for testing) and it's really speeding up my work and simplifying my code. With a modern IDE with text-replacements and so on it's not that hard to extract an interface later on if you REALLY need it (very rare for me). That's just my personal opinion.