标签:
目标对象:被通知的对象。既可以是你编写的类也可以是第三方类。
代理:将通知应用到目标对象后创建的对象,应用系统的其他部分不用为了支持代理对象而改变。
在spring中所有的通知都是以java类的形式编写的。切入点定义在配置文件中编写,所以切面代码和配置文件对我们来说都很熟悉。
对于其他框架(Aspectj),需要特定的语法编写,如果使用的话,还需学习新的语言。
spring的运行时通知对象
spring在运行期创建代理,不需要特殊的编译器.
spring有两种代理方式:
若目标对象实现了若干接口,spring使用JDKjava.lang.reflect.Proxy类代理。该类让spring动态产生一个新类,它实现了所需的接口,织入了通知,并且代理对目标对象的所有请求。
若目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类。使用该方式时需要注意:
2.1对接口创建代理优于对类创建代理,因为会产生更加松耦合的系统。
对类代理是让遗留系统或无法实现接口的第三方类库同样可以得到通知,这种方式应该是备用方案。
2.2.标记为final的方法不能够被通知。spring是为目标类产生子类。任何需要被通知的方法都被复写,将通知织入。final方法是不允许重写的。
spring只支持方法连接点:不提供属性接入点,spring的观点是属性拦截破坏了封装。面向对象的概念是对象自己处理工作,其他对象只能通过方法调用的得到的结果。
通知类型 | 接口 | 描述 |
---|---|---|
Around | MethodInterceptor | 拦截对目标方法调用 |
Before | MethodBeforeAdvice | 在目标方法调用前调用 |
After | AfterReturningAdvice | 在目标方法调用后调用 |
Throws | ThrowsAdvice | 当目标方法抛出异常时调用 |
public interface MethodBeforeAdvice
{
void before(Method m,Object[] os ,Object target)
{
}
}
该接口提供了获得目标方法、参数和目标对象的机会。不能够改变运行时参数,即不能替换参数对象和目标对象。
注意:在方法结束后不返回任何值东西。原因是该接口返回后,目标方法将会被调用,应该返回目标对象的返回值。该接口唯一能阻止目标方法被调用的途径是抛出异常或(System.exit())。
package jiankunking.aop;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class MyMethodBeforeAdvice implements MethodBeforeAdvice
{
/**
* method: 被调用方法名字
* args: 给method传递的参数
* target: 目标对象
*/
public void before(Method method, Object[] args, Object target)
throws Throwable
{
System.out.println("*****************************************"+"");
System.out.println("MethodBeforeAdvice在目标方法调用前调用..." + method.getName());
}
}
ProxyFactoryBean是一个在BeanFactory中显式创建代理对象的中心类,可以给它一个要实现的接口、一个要代理的目标对象、一个要织入的通知,并且他将创建一个崭新的代理对象。
同前置通知类似:
public interface AfterReturningAdvice{
public void afterReturning(Object returnValue,Method
m,Object[] os,Object target);
}
public interface MethodInterceptor extends Interceptor{
Object invoke(MethodInvocation invocation);
}
该接口同前两种通知有两个重要区别:
public interface ThrowsAdvice{
}
该接口为标识性接口,没有任何方法,但实现该接口的类必须要有如下形
式的方法:
public void afterThrowing(Throwable throwable)
{
}
public void afterThrowing(Method m,Object[] os,Object
target,Exception throwable)
{
}
第一个方法只接受一个参数:需要抛出的异常。
第二个方法接受异常、被调用的方法、参数以及目标对象。
以前定义的通知类型是在目标对象的方法被调用的周围织入。引入通知给目标对象添加新的方法和属性。
如果不能表达在应用系统的什么地方应用通知的话,通知将毫无用处,这就是切入点的用处。切入点决定了一个特定的类的特定方法是否满足一定的规则。若符合,通知就应用到该方法上。
<?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-2.5.xsd"
>
<!-- 配置被代理的对象 -->
<bean id="test1Service" class="jiankunking.aop.Test1Service">
<property name="name" value="小土豆"/>
</bean>
<!--前置通知-->
<bean id="myMethodBeforeAdvice" class="jiankunking.aop.MyMethodBeforeAdvice"/>
<!--后置通知-->
<bean id="myAfterReturningAdvice" class="jiankunking.aop.MyAfterReturningAdvice"/>
<!--环绕通知-->
<bean id="myMethodInterceptor" class="jiankunking.aop.MyMethodInterceptor"/>
<!--异常通知-->
<bean id="myThrowsAdvice" class="jiankunking.aop.MyThrowsAdvice"/>
<!--定义前置通知的切入点-->
<bean id="nameMatchMethodPointcutAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice" ref="myMethodBeforeAdvice"/>
<property name="mappedNames">
<list>
<value>
sayHello
</value>
</list>
</property>
</bean>
<!-- 配置代理对象 -->
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 代理接口集 -->
<property name="proxyInterfaces">
<list>
<value>jiankunking.aop.TestServiceInterface</value>
<value>jiankunking.aop.TestServiceInterface2</value>
</list>
</property>
<!-- 把通知织入到代理对象 -->
<property name="interceptorNames">
<list>
<!-- 相当于包MyMethodBeforeAdvice前置通知和代理对象关联,我们也可以把通知看出拦截器,struts2核心拦截器 -->
<!--<value>myMethodBeforeAdvice</value>-->
<!--使用自定义切入点来控制前置通知-->
<value>nameMatchMethodPointcutAdvisor</value>
<!--织入后置通知-->
<value>myAfterReturningAdvice</value>
<!--织入环绕通知-->
<value>myMethodInterceptor</value>
<!--织入异常通知-->
<value>myThrowsAdvice</value>
</list>
</property>
<!-- 配置被代理对象,可以指定 -->
<property name="target" ref="test1Service"/>
</bean>
</beans>
正则表达式切入点(RegexpMethodPointcut):
具体案例参考demo:Spring Aop 演示demo
作者:jiankunking 出处:http://blog.csdn.net/jiankunking
本文部分内容整理自网络
标签:
原文地址:http://blog.csdn.net/jiankunking/article/details/51933256