如何配置及使用Spring拦截器(通知)
1.Spring有五种通知类型本文着重讲述3中:前置通知,后置通知,环绕通知。
2.前置通知:在运行目标方法之前运行。
2.1:前置通知的配置:第一步:新建一个类,实现MethodBeforeAdvice接口,并且复写其中的before方法。
import java.lang.reflect.Method;
import java.util.Arrays;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.stereotype.Component;
@Component("beforeAdvice")
public class BeforeAdvice implements MethodBeforeAdvice
{
@Override
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable
{
//arg0:目标方法的本身可以通过反射执行此方法
//arg1:arg0方法的参数列表
//arg2:arg2拥有此方法的对象
String name = arg0.getName();
System.out.println(name);
arg0.invoke(arg2.getClass().newInstance());
System.out.println("我是前置通知");
System.out.println("方法本身:" + arg0 + "参数列表:" + Arrays.toString(arg1) + "拥有此方法的对象" + arg2);
}
}
before方法有三个参数,其中Method arg0代表的是目标方法本身(目标方法就是你需要运行的方法)Object[] arg1代表的是目标方法的参数列表,object arg3代表的是目标方法所属的对象。
第二步:将此类给加上Spring注解,将其放到IOC容器中,或者直接在applicationContent.xml中配置
<bean id="beforeAdvice" class="com.bjsxt.pojo.Student" >
第三步:看看你的spring配置文件的DTD中有没有以下标红的三个内容,没有的话直接粘贴复制我的给加上就好了
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"
default-autowire="byName">
没有上面标红的三句生命的话,你的xml中是没有AOP标签的;
第四步:在applicationContent.xml中配置前置通知
<!-- 配置AOP --> <aop:config> <!-- 切面定义 expression(固定的):哪些类里面的哪些方法执行下面的BeforeAdvice *:第一个*表示返回值:*任意类型
com.bjsxt.service.impl.UsersServiceImpl:哪些类*:方法;当前类下面的所有方法(..)参数:任意类型的参数 --><aop:pointcut expression="execution(* com.bjsxt.service.impl.*.*(..))" id="pointcut"/><!-- 通知类型将beforeAdvice关联到上面的横切面中(pointcut) --><aop:advisor advice-ref="beforeAdvice" pointcut-ref="pointcut"/></aop:config></beans> 到此就配置好了,写个测试类测试一下。例如:execution(* com.bjsxt.service.impl.*.*(..)) 代表com.bjsxt.service.impl包下的任何类的任何方法都触发通知
测试类:
控制台输出:import org.junit.Before; import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Component; @Component("test") public class SpringTest { ClassPathXmlApplicationContext ac =null; @Before public void inti() { //初始化 得到spring配置文件对象 ac ac = new ClassPathXmlApplicationContext("applicationContext.xml"); } @Test public void test() { SpringTest test = (SpringTest)ac.getBean("test"); test.save(); } public void save() { System.out.println("-----------------save---------------"); } }
十一月 15, 2016 9:02:53 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@e6ea0c6: startup date [Tue Nov 15 09:02:53 CST 2016]; root of context hierarchy 十一月 15, 2016 9:02:54 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [applicationContext.xml] save -----------------save--------------- 我是前置通知 -----------------save--------------- 方法本身:public void com.bjsxt.test.SpringTest.save()参数列表:[]拥有此方法的对象com.bjsxt.test.SpringTest@581ac8a8
3.通过注解来配置和使用前置通知。
第一步:在applicationContent.xml中开启通知注解:加入如下的一个标签就好
<!-- 开启AOP的注解 -->
<aop:aspectj-autoproxy/>
第二步:在通知类的类声明上加上@Ascept注解。
package com.bjsxt.springaop.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Component("myAdciceAnno") @Aspect public class MyAdviceAnno { @Before(value="execution(* com.bjsxt.test.*.*(..))")//表示的是那些包的那些类的那些方法作为目标方法,在执行之前需要执行这个前置通知。 public void before() { System.out.println("我是前置通知"); } @After(value="execution(* com.bjsxt.test.*.*(..))") public void after() { System.out.println("我是后置通知"); } @Around(value="execution(* com.bjsxt.test.*.*(..))") public void cross(ProceedingJoinPoint pjp) throws Throwable { System.out.println("我是环绕通知------------before"); pjp.proceed(); System.out.println("我是环绕通知------------after"); } }