Spring中重要的概念:基于AOP切面编程:(其实就是在方法的前后加入执行代码)
切面:Aspect:即由切入点(PointCut)和通知(Advice)
切入点:就是需要加入切面代码的地点(通常是某个方法名称,实际中用正则来匹配)。
通知:就是切入点发生后要做的事情,比如执行某段代码。
首先Spring支持5中通知:
(1)Before(前)
(2)After-returning(返回后) org.springframework.aop.AfterReturningAdvice
(3)After-throwing(抛出后) org.springframework.aop.ThrowsAdvice
(4)Arround(周围) org.aopaliance.intercept.MethodInterceptor
(5)Introduction(引入) org.springframework.aop.IntroductionInterceptor
可以看出都是对某个方法进行通知(也证实了AOP的实际含义就是在某个方法前后加入代码段的概念)
先首先用代理模式怎么实现AOP
(1)创建通知:实现这几个接口,把其中的方法实现了
(2)创建切入点:一般通过正则匹配
(3)定义切面(把通知和切入点整合):常用的切面类有:
NameMatchMethodPointcutAdvisor,JdkRegexpMethodPointcut, DefaultPointcutAdvisor
(4)使用ProxyFactoryBean来生成代理,需指定要代理的接口和实现类,并把切面配置进去
具体:
1、先定义一个通知:用Arround
public class MethodAroundInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
System.out.println("Method around before " + arg0.getMethod().getName());
arg0.proceed(); //是否要调用切面代码
System.out.println("Method around after " + arg0.getMethod().getName());
return null;
}
配置通知:
<span style="white-space:pre"> </span><bean id="withAopAdvice" class="ray.interceptor.MethodAroundInterceptor"/>
2、定义一个切入点:
<bean id="withAopPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value=".*withAop" />
</bean>
3、定义一个切面:(这里用DefaultPointcutAdvisor)
<bean id="withAopAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="withAopAdvice" />
<property name="pointcut" ref="withAopPointcut" />
</bean>
最后要在代理中配置
<bean id="aopServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="ray.aop.IAopService" />
<!-- 制定需要代理的对象(接口实现类) -->
<property name="target"> <ref bean="aopService" />
</property>
<!-- before - arround before - method - arround after - after -->
<property name="interceptorNames"><!-- 定义通知 -->
<list>
<value>withAopAdvisor</value>
</list>
</property>
</bean>
4、测试下:
private static void TestInterceptor() {
//通过代理类获得bean实例,其实是在代理类中方法执行前后加入代码
IAopService service = (IAopService)factory.getBean("aopServiceProxy");
//如果用构造函数或者工厂方法获得bean实例,不能实现AOP
// IAopService service = (IAopService) factory.getBean("aopService");
service.withAop();
service.withOutAop();
}
看下输出:
Method around before withAop
run withAop method---------
Method around after withAop
run withOutAop method---------
另外:Spring给我们封装了几个常用的切面:
例如: NameMatchMethodPointcutAdvisor
上面的配置就可以这样配置了:
<!-- 要是拦截器在某个方法后执行,需要安装到NameMathched。。Advisor中 -->
<bean id="aopMethodThrowsExceptionInterceptor"
class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice">
<bean class="ray.interceptor.MethodThrowExceptionInterceptor"></bean>
</property>
<property name="mappedName" value=".*withAop"></property>
</bean>
只是把切入点的配置换成了mappedName而已,因为里面封装了mappedName为切入点: