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. //向前增强