SpringAop及拦截器
一、Aop
Aop,面向切面编程,提供了一种机制,在执行业务前后执行另外的代码。
切面编程包括切面(Aspect),连接点(Joinpoint)、通知(Advice)、切入点(Pointcut)、引入(Introduction)
通知(Advice)又分为前置通知,后置通知,最终通知,环绕通知,异常通知等。
在Spring中,Aop思想可以通过拦截器体现。
二、Aop应用:
1.Junit单元测试中,也用到了AOP思想,比如其中的before(),after()方法。
2.事务管理。业务逻辑之前是事务的开启begin,业务逻辑之后是事务的提交commit。
3.日志的管理。过滤,格式处理等
4.Spring中的拦截器。
三、拦截器:
在Spring中,拦截器可以分为方法前执行的拦截器、方法后执行的拦截器、异常拦截器
1.方法前拦截器类,需要实现MethodBeforeAdvice接口;
2.方法后拦截器类,需要实现AfterReturningAdvice接口;
3.异常拦截器类,需要实现ThrowsAdvice接口.
四、拦截器中的Aop及代理模式:
Advisor(通知):实现了Advice接口的拦截器(interceptor),是AOP中的Advisor(通知)
Pointcut(切入点):NameMatchMethodPointcutAdvisor类是AOP中的Pointcut(切入点),
将各种拦截器配置到NameMatchMethodPointcutAdvisor上。
"切入点"负责指定区域,而"通知"负责插入指定的代码。
Spring无法将Service实现类与拦截器类直接组装,因此没有对应的getter、setter方法,
安装时借助的是Spring的代理类ProxyFactoryBean,即把拦截器安装到切入点NameMatchMethodPointcutAdvisor中,
把自定义的Service安装到ProxyFactoryBean中,然后组装在一起.(代理模式)
ProxyFactoryBean通过setInterceptorNames()方法设置拦截器,通过setTarget()方法设置拦截对象,可以在xml中配置 。
五、区分Filter(过滤器)和Interceptor(拦截器):
四、示例如下:
Service接口:
public interface IAopService { public void withAop() throws Exception; public void withoutAop() throws Exception; }
Service接口实现类:
import javax.security.auth.login.AccountException; public class AopServiceImpl implements IAopService { private String name; @Override public void withAop() throws Exception { System.out.println("有AOP的函数运行。name: " + name); if (name.trim().length() == 0) { throw new AccountException("name属性不能为空"); } } @Override public void withoutAop() throws Exception { System.out.println("没有AOP的函数运行。"); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
三个拦截器如下所示:
方法前拦截器如下:
import org.springframework.aop.MethodBeforeAdvice; import java.lang.reflect.Method; public class MethodBeforeInterceptor implements MethodBeforeAdvice { @Override public void before(Method method, Object[] args, Object instance) throws Throwable { System.out.println("即将要执行方法:" + method.getName()); if (instance instanceof AopServiceImpl) { String name = ((AopServiceImpl) instance).getName(); if (name == null) { throw new NullPointerException("name属性不能为null"); } } } }
方法后拦截器如下:
import org.springframework.aop.AfterReturningAdvice; import java.lang.reflect.Method; public class MethodAfterInterceptor implements AfterReturningAdvice { @Override public void afterReturning(Object value, Method method, Object[] args, Object instance) throws Throwable { System.out.println("方法 " + method.getName() + "运行完毕,返回值为:" + value); } }
异常拦截器如下:
import org.springframework.aop.ThrowsAdvice; import javax.security.auth.login.AccountException; import java.lang.reflect.Method; public class ThrowsInterceptor implements ThrowsAdvice { public void afterThrowing(Method method, Object[] args, Object instance, AccountException ex) throws Throwable { System.out.println("方法" + method.getName() + " 抛出了异常:" + ex); } public void afterThrowing(NullPointerException ex) throws Throwable { System.out.println("抛出了异常:" + ex); } }
Main方法如下:
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AopRun { public static void main(String[] args) throws Exception { ApplicationContext context= new ClassPathXmlApplicationContext("applicationContext.xml"); IAopService aopService = (IAopService) context.getBean("aopService"); aopService.withAop(); aopService.withoutAop(); } }
applicationContext.xml如下:
<!--将拦截器配置到代理类上-->
<bean id="aopService" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--拦截器-->
<property name="interceptorNames">
<list>
<value>aopMethodBeforeInterceptor</value>
<value>aopMethodAfterInterceptor</value>
<value>aopThrowInterceptor</value>
</list>
</property>
<!--拦截对象 -->
<property name="target">
<bean class="com.aop.AopServiceImpl">
<property name="name" value="Rui"></property>
</bean>
</property>
</bean>
<!--拦截器在方法前运行,安装到NameMatchMethodPointcutAdvisor-->
<bean id="aopMethodBeforeInterceptor"
class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice">
<bean class="com.aop.MethodBeforeInterceptor"></bean>
</property>
<property name="mappedName" value="withAop"></property>
</bean>
<!--拦截器在方法后运行,安装到NameMatchMethodPointcutAdvisor-->
<bean id="aopMethodAfterInterceptor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice" >
<bean class="com.aop.MethodAfterInterceptor"></bean>
</property>
<property name="mappedName" value="withAop"></property>
</bean>
<!--拦截器在异常抛出运行,安装到NameMatchMethodPointcutAdvisor-->
<bean id="aopThrowInterceptor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice">
<bean class="com.aop.ThrowsInterceptor"></bean>
</property>
<property name="mappedName" value="withAop"></property>
</bean>
注:示例摘自《JavaWeb整合开发王者归来》