AOP联盟为了增强定义了org.framework,aop.Adivce接口,Spring 支持5种类型的增强,下面是增强接口的关系图

Spring支持5种类型的增强:
1.前置增强:org.springframework.aop.BeforeAdvice代表前置增强,因为Spring只支持
方法级的增强,所以MethodBeforeAdvice是目前可的的前置增强,表示在目标方法执行前
实施增强,而BeforeAdvice是为了将来版本扩展需要而定义的;

2.后置增强:org.springframework.aop.AfterReturningAdvice代表后增强,表示在目标
方法执行后实施增强;

3.环绕增强:org.aopalliance.intercept.MethodInterceptor代表环绕增强,表示在目标
方法执行前后实施增强;

4:异常抛出增强:org.springframework.aop.ThrowsAdvice代表抛出异常增强,表示在目
标方法抛出异常后实施增强;

5.引介增强:org.springframework.aop.InteoductionInterceptor代表引介增强,表示在
目标类中添加一些新的方法和属性;

这些增强接口都有一些方法,通过实现这些接口方法,在接口方法中这义横切逻辑,就可以
将它们织入到目标类的方法的相应连接点的位置。

向前增强


保证有礼貌说话的实例


1.这个Waiter 目前就只有这两个行为


package com.hegx.spring.aop.beforeadvice;

/**
 * @Author: hegx
 * @Description:
 * @Date: 17:50 2017/7/16
 */
public interface Waiter {

    void greetTo(String name);
    void serveTo(String name);
}

现在我们来看一个训练不足的服务生的情况:


package com.hegx.spring.aop.beforeadvice;

/**
 * @Author: hegx
 * @Description:
 * @Date: 17:51 2017/7/16
 */
public class NaiveWaiter implements Waiter {

    @Override
    public void greetTo(String name) {
        System.out.println("greet to"+name+"...");
    }

    @Override
    public void serveTo(String name) {
        System.out.println("serve to"+name+"...");
    }
}

从上面来看 这个服务生的确是没有礼貌的,所有我们应该想办法增强一下他,让他变得有礼貌起来


package com.hegx.spring.aop.beforeadvice;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

/**
 * @Author: hegx
 * @Description:自定义的前置增强
 * @Date: 17:52 2017/7/16
 */
public class GreetionBeforeAdvice implements MethodBeforeAdvice {

    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {

        String clientName = (String) objects[0];

        System.out.println("How are you!"+clientName+".");
    }
}

通过增强以后,这个服务生应该是有礼貌很多了,我们来看测试一下是不是真的:


package com.hegx.spring.aop.beforeadvice;


import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;

/**
 * @Author: hegx
 * @Description:前置增强测试
 * @Date: 17:54 2017/7/16
 */
public class TestBeforAdvice {

    public static void main(String[] args) {

        NaiveWaiter target = new NaiveWaiter();
        BeforeAdvice advice = new GreetionBeforeAdvice();

        //Spring提供的代理工厂
        ProxyFactory factory = new ProxyFactory();
        //设置代理目标
        factory.setTarget(target);
        //为代理类设置增强
        factory.addAdvice(advice);
        //生成代理实例
        Waiter proxy = (Waiter) factory.getProxy();
        proxy.greetTo("Tom");
        proxy.serveTo("hgx");
    }

}

程序运行结果:


How are you!Tom.
greet toTom...
How are you!hgx.
serve tohgx...
正如我们期望看到的那样,服务员彬彬有礼起来了!


在Spring配置中配置


<?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="greetAdvice" class="com.hegx.spring.aop.beforeadvice.GreetionBeforeAdvice"></bean>

    <!--目标增强对象-->
    <bean id="target" class="com.hegx.spring.aop.beforeadvice.NaiveWaiter"></bean>

    <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--指定代理的接口,如果多个话可以使用list标签-->
        <property name="proxyInterfaces" value="com.hegx.spring.aop.beforeadvice.Waiter"/>

        <!--指定使用的增强-->
        <property name="interceptorNames" value="greetAdvice"/>

        <!--指定对哪个bean进行处理-->
        <property name="target" ref="target"/>
    </bean>

</beans>

测试:


package com.hegx.spring.aop.beforeadvice;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Author: hegx
 * @Description:
 * @Date: 19:52 2017/7/16
 */
public class TestProxyBeanFactory {

    public static void main(String[] args) {

        ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:config/ProxyFactoryBean.xml");
        Waiter waiter= (Waiter) ac.getBean("waiter");
        waiter.greetTo("hegx");
    }

}

输出结果:


How are you!hegx.
greet tohegx...




这是ProxyFactoryBean使用的了JDK的代理技术,我们可以调整配置,使用CGLib代理技术通过动态创建NaiveWaiter的自来来代理NaiveWaiter对象:


<?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="greetAdvice" class="com.hegx.spring.aop.beforeadvice.GreetionBeforeAdvice"></bean>

    <!--目标增强对象-->
    <bean id="target" class="com.hegx.spring.aop.beforeadvice.NaiveWaiter"></bean>

    <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--JDK动态代理机制方式 指定代理的接口,如果多个话可以使用list标签-->
        <!--<property name="proxyInterfaces" value="com.hegx.spring.aop.beforeadvice.Waiter"/>
-->
        <!--CGLib代理技术方式-->
        <property name="proxyTargetClass" value="true"/>
        <!--指定使用的增强-->
        <property name="interceptorNames" value="greetAdvice"/>

        <!--指定对哪个bean进行处理-->
        <property name="target" ref="target"/>
    </bean>

</beans>


interceptorNames设置为true后,无须再设置 proxyInterfaces属性,及时设置了属性也会被ProxyFactoryBean忽略。





package com.hegx.spring.aop.afteradvice;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

/**
 * @Author: hegx
 * @Description:
 * @Date: 20:10 2017/7/16
 */
public class AfterGreetAdvice implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("Please enjoy yourself!");
    }
}
<?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="greetAdvice" class="com.hegx.spring.aop.beforeadvice.GreetionBeforeAdvice"/>

    <bean id="afterGreetAdvice" class="com.hegx.spring.aop.afteradvice.AfterGreetAdvice"/>

    <!--目标增强对象-->
    <bean id="target" class="com.hegx.spring.aop.beforeadvice.NaiveWaiter"></bean>

    <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--JDK动态代理机制方式 指定代理的接口,如果多个话可以使用list标签-->
        <!--<property name="proxyInterfaces" value="com.hegx.spring.aop.beforeadvice.Waiter"/>
-->
        <!--CGLib代理技术方式-->
        <property name="proxyTargetClass" value="true"/>
        
  <property name="interceptorNames">
            <list>
                <idref bean="greetAdvice"/>
                <idref bean="afterGreetAdvice"/>
            </list>
        </property>
     <!--指定对哪个bean进行处理-->
        <property name="target" ref="target"/>
    </bean>

</beans>
How are you!hegx. //向前增强