Advice - Advisor - NameMatchMethodPointcutAdvisor

in yes particular order!

Directory Layout
MacBook-Pro:springaopexamples koraytugay$ tree
.
├── pom.xml
└── src
    └── main
        ├── java
        │   └── biz
        │       └── tugay
        │           └── springaopexamples
        │               ├── App.java
        │               └── foo
        │                   ├── Foo.java
        │                   └── FooImpl.java
        └── resources
            └── beans.xml
 
8 directories, 5 files

pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/maven-v4_0_0.xsd">
 
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>biz.tugay</groupId>
    <artifactId>bare-maven-project</artifactId>
    <packaging>jar</packaging>
 
    <version>1.0-SNAPSHOT</version>
 
    <name>bare-maven-project</name>
    <url>http://www.tugay.biz</url>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>
    </dependencies>
 
    <build>
        <directory>/Users/koraytugay/target/${project.name}</directory>
        <finalName>bare-maven-project</finalName>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                    <mainClass>biz.tugay.springaopexamples.App</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
 
    <properties>
        <project.name>springaopexamples</project.name>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
</project>

beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans 
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">
 
    <bean id="foo" class="biz.tugay.springaopexamples.foo.FooImpl"/>
    <bean id="fooProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="targetName" value="foo"/>
    </bean>
</beans>

App.java
package biz.tugay.springaopexamples;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import biz.tugay.springaopexamples.foo.Foo;
 
public class App {
 
    public static void main(String[] args) {
        final ApplicationContext appContext 
            = new ClassPathXmlApplicationContext("beans.xml");
        final Foo fooProxy = appContext.getBean("fooProxy", Foo.class);
        fooProxy.foo();
    }
}

Execution
MacBook-Pro:springaopexamples koraytugay$ mvn clean install exec:java -q
Nov 19, 2017 11:28:42 AM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@35a6a913: startup date [Sun Nov 19 11:28:42 CET 2017]; root of context hierarchy
Nov 19, 2017 11:28:43 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans.xml]
FooImpl#foo

Notes

Example above demonstrates a very simple usage of the ProxyFactoryBean. Lets slowly get deeper by reading the related documentation.

Do not forget the fact that: In Spring AOP, an Aspect is represented by an instance of a class that implements the Advisor interface.

We will be using the setInterceptorNames method initially, the documentation says:
Set the list of Advice/Advisor bean names. This must always be set to use this factory bean in a bean factory.
The referenced beans should be of type Advisor or Advice.
So what happens when we add an Advice instead of an Advisor? It is explained here.
Add the given AOP Alliance advice to the tail of the advice (interceptor) chain. 
This will be wrapped in a DefaultPointcutAdvisor with a pointcut that always applies, and returned from the getAdvisors() method in this wrapped form. 
Note that the given advice will apply to all invocations on the proxy, even to the toString() method! Use appropriate advice implementations or specify appropriate pointcuts to apply to a narrower set of methods.
Let us start simple and add an Advice:

Bar.java
package biz.tugay.springaopexamples.bar;
 
public interface Bar {
    void bar();
}

BarImpl.java
package biz.tugay.springaopexamples.bar;
 
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
 
public class BarImpl implements Bar, MethodBeforeAdvice {
 
    @Override
    public void bar() {
        System.out.println("BarImpl#bar");
    }
 
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        bar();
    }
}

beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans 
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">
 
    <bean id="foo" class="biz.tugay.springaopexamples.foo.FooImpl"/>
    <bean id="bar" class="biz.tugay.springaopexamples.bar.BarImpl"/>
 
    <bean id="fooProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="targetName" value="foo"/>
        <property name="interceptorNames">
            <list>
                <value>bar</value>
            </list>
        </property>
    </bean>
 
</beans>

App.java
package biz.tugay.springaopexamples;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import biz.tugay.springaopexamples.foo.Foo;
 
public class App {
 
    public static void main(String[] args) {
        final ApplicationContext appContext 
            = new ClassPathXmlApplicationContext("beans.xml");
        final Foo fooProxy = appContext.getBean("fooProxy", Foo.class);
        fooProxy.foo();
        System.out.println(fooProxy);
    }
}

Execution
MacBook-Pro:springaopexamples koraytugay$ mvn clean install exec:java -q
Nov 19, 2017 12:11:40 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@44e2cd21: startup date [Sun Nov 19 12:11:40 CET 2017]; root of context hierarchy
Nov 19, 2017 12:11:40 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans.xml]
BarImpl#bar
FooImpl#foo
BarImpl#bar
biz.tugay.springaopexamples.foo.FooImpl@39dc44b6

Moving Forward with Advisor instead of Advice..

Lets use an Advisor instead of an Advice.. Instead of implementing our own Advisor, lets use: NameMatchMethodPointcutAdvisor.

The only difference we will make is in the beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans 
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">
 
    <bean id="foo" class="biz.tugay.springaopexamples.foo.FooImpl"/>
    <bean id="bar" class="biz.tugay.springaopexamples.bar.BarImpl"/>
 
    <bean id="barAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
        <property name="advice" ref="bar"/>
        <property name="mappedName" value="foo"/>
    </bean>
 
    <bean id="fooProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="targetName" value="foo"/>
        <property name="interceptorNames">
            <list>
                <value>barAdvisor</value>
            </list>
        </property>
    </bean>
</beans>

Execution

MacBook-Pro:springaopexamples koraytugay$ mvn clean install exec:java -q
Nov 19, 2017 12:26:16 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@26230076: startup date [Sun Nov 19 12:26:16 CET 2017]; root of context hierarchy
Nov 19, 2017 12:26:16 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans.xml]
BarImpl#bar
FooImpl#foo
biz.tugay.springaopexamples.foo.FooImpl@6ac481fa

Summary

We moved from adding an Advice to a default Advisor to a specific Advisor!