前言:最近在复习spring特记录于此,欢迎大家交流指正 QQ:767872620
spring提供两种切面编程的使用方式:
(1)基于注解方式进行AOP开发
(2)基于xml配置方式进行AOP开发
一、环境配置
1.在配置文件中引入aop命名空间
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation中导入:
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
2.导入jar包
http://www.springsources.org/downl
dist\spring.jar
lib\jakarta-commons\commons-logging.jar
使用aop另外导入:
lib\aspectj\aspectjweaver.jar和aspectjrt.jar
lib\cglib\cglib-nodep-2.2.2.jar
使用JSR-250中的注解,如@Resource
commons-annotations.jar
二、基于注解方式进行AOP开发
启动对@AspectJ注解的支持
<!-- 引入注解解释器 -->
<aop:aspectj-autoproxy/>
例子代码如下:
依然是熟悉的Person相关业务类
public interface PersonService { public void save(String name); public void update(String name,Integer id); public String getPersonName(); public String getPersonName(Integer id); }
package cn.itcast.service.imp; import cn.itcast.service.PersonService; public class PersonServiceBean implements PersonService { public String getPersonName() { System.out.println("我是getPersonName()"); return "xxx"; } public String getPersonName(Integer id) { System.out.println("我是getPersonName()"); return "xxx"; } public void save(String name) { throw new RuntimeException("我爱意外"); //用于测试意外通知 // System.out.println("我是save()"); } public void update(String name, Integer id) { System.out.println("我是update()"); } }
切面代理类(注解实现):
package cn.itcast.service; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; /** * 通过注解声明为切面 * @author Mars * */ Aspect //将此类标记为拦截类(代理类) public class MyInterceptor { /** * * 1.拦截方法 * @Pointcut("execution(* cn.itcast.service..*.*(..)))") * execution:执行业务方式是进行拦截 * *:返回值类型,*代表任何返回值类型 * cn.itcast.service:包名 * ..:对子包也进行拦截 * *:包下的什么类,*代表对所有类进行拦截 * *:指方法,*代表对所有的方法进行拦截 * ..:指方法的参数随意 */ @Pointcut("execution(* cn.itcast.service.imp.PersonServiceBean.*(..))") private void anyMethod(){} //声明一个切入点 /* *//** * 2.前置通知 * 拦截方法后在执行业务方法之前进行执行 * 注解参数为切入点方法的名称,记得加括号 * 暂时不要参数 *//* @Before("anyMethod()") public void doAccessCheck(){ System.out.println("你好!我是前置通知,下面请业务方法闪亮登场"); }*/ /** * 前置通知 * 获取执行业务方法的用户输入参数 * @Before("anyMethod() && args(username)") * 拦截到的方法参数必须是一个,而且是必须是String的才会进入前置通知 * 其他的方法不执行前置通知方法 * 注解中的args(username)与public void doAccessCheck(String username)的参数必须一样 * */ @Before("anyMethod() && args username)") public void doAccessCheck(String username){ System.out.println("前置参数:"+username+"你好!我是前置通知,下面请业务方法闪亮登场"); } /* *//** * 2.后置通知 * 拦截方法后在执行业务方法之后进行执行 * 注解参数为切入点方法的名称,记得加括号 * 暂时不要参数 *//* @AfterReturning("anyMethod()") public void doAfterReturning(){ System.out.println("业务方法执行完了,该我后置通知了!"); }*/ /** * 后置通知 * 获取业务方法的返回值 * 说明: * 注解参数returning="result"作用 * 1.获取业务方法返回值的类型为String类型 * 2.获取的返回值最为后置通知的参数传入后置方法 */ @AfterReturning(pointcut="anyMethod()",returning="result") public void doAfterReturning(String result){ System.out.println("业务方法执行完了,该我后置通知了!"+result); } /** * 3.最终通知 * 后置通知执行完后执行最终通知 */ @After("anyMethod()") public void doAfter(){ System.out.println("后置通知完事了!是我最终通知"); } /* *//** * 4.意外通知 * 当执行业务方法时抛异常,执行意外通知 * 后置通知不会在被执行,前置通知、最终通知、意外通知都会被执行 *//* @AfterThrowing("anyMethod()") public void doAfterThrowing(){ System.out.println("意外通知"); }*/ /**意外通知 * 获取业务方法抛出的意外 * */ @AfterThrowing(pointcut="anyMethod()", throwing=" e") public void doAfterThrowing( Exception e){ System.out.println("意外通知" + e); } /* * * 5.环绕通知 * 必须在环绕通知内部执行pjp.proceed(); * 否则后面的切面和业务方法不会被执行。 * 执行顺序: *环绕通知->后面的切面(可以没有)-->目标对象的业务方法 */ @Around("anyMethod()") public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable{ //if(){//判断用户是否有权限 System.out.println("进入环绕通知方法"); Object result = pjp.proceed(); System.out.println("退出环绕通知方法"); //} return result; } }
配置文件:
<?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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <aop:aspectj-autoproxy/> <!-- 通过xml配置bean将拦截类交由spring管理 --> <bean id="myInterceptor"class="cn.itcast.service.MyInterceptor"></bean> <bean id="PersonService"class="cn.itcast.service.imp.PersonServiceBean"></bean> </beans>
测试类(有点简陋):
package junit.test; import org.junit.BeforeClass; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.itcast.service.PersonService; public class SpringAOPTest { @BeforeClass public static void setUpBeforeClass() throws Exception{ } @Test public void interceptorTest(){ ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml"); PersonService personservice = (PersonService)cxt.getBean("PersonService"); personservice.save("xxx"); // personservice.getPersonName(2); } }