前面的各种Aop编程,都是基于XML的,这篇文章讲的是把XML方式改为注解方式来做。
Spring注解开发和xml开发所需要的包是一样的,所以只要把xml开发方式的包复制到以注解为开发方式的包的项目下就可以了。
第一步:导入相应的jar包
第二步:需要在applicationContext.xml中引入aop的名称空间
开启注解自动代理:
<!-- 自动注解 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
第三步:AOP编程:
第(一)步.目标对象:
//编写目标类(真正被代理的) public class UserDaoImpl implements UserDao { public int delete() { System.out.println("删除了"); return 1; } }
第(二)步:编写切面类和Advice方法
//这个注解表明这个类就是切面类,在这个类里面可以写Advice(通知)方法。@Aspect public class Myspect { //我们配置一个前置方法的Advice方法,这是一个Advice方法,当然要配置切点了。配了切点就表示在这个切点执行这个Advice方法。 @Before("execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))") public void before1(JoinPoint joinPoint) { System.out.print("this is 前置方法"); } //后置通知,这是一个Advice方法,当然要配置切点了。配了切点就表示在这个切点执行这个Advice方法。 @AfterReturning(value="execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))",returning="returnVal") public void afterReturning(JoinPoint joinPoint,Object returnVal) { System.out.println("this is afterReturning 方法"); System.out.println(returnVal); } }
第四步:在Spring配置文件中配置目标Bean和切面Bean
<!-- xml配置目标bean和切面bean --> <bean id="UserDao" class="com.guigu.shen.anotion.UserDaoImpl"></bean> <bean id="Myspect" class="com.guigu.shen.anotion.Myspect"></bean>
接下来给出Aspect5种通知的注解形式的具体实例
前置通知@Before
//前置通知@Before("execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))") public void before1(JoinPoint joinPoint) { System.out.print("this is 前置方法"); }
后置通知:
//后置通知 @AfterReturning(value="execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))",returning="returnVal") public void afterReturning(JoinPoint joinPoint,Object returnVal) { System.out.println("this is afterReturning 方法"); System.out.println(returnVal); }
环绕通知:
//环绕通知,在方法的前后执行,在工作中可以计算方法执行的时间,性能的监控,权限的设置,缓存的实行等 @Around("execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))") public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { long begintime=System.currentTimeMillis(); Object result=proceedingJoinPoint.proceed(); long endtime=System.currentTimeMillis(); System.out.println("方法执行了"+(endtime-begintime)+"时间"); return result; }
异常通知:指的是当发生一些异常时会输出异常信息(如果方法没有异常的话,这个通知不会被执行的,比如如果.UserDaoImpl中的delete()方法会产生一个异常,
那么这个切点通知方法会执行,如果UserDaoImpl中的delete()方法没哟异常就不会执行这个方法)
@AfterThrowing(value="execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))",throwing="e") public void afterThrowing(JoinPoint joinPoint,Exception e) { System.out.print(joinPoint.toLongString()+"方法发生了异常"+e.getMessage()); }
情形一:
被代理类的方法:
//编写目标类(真正被代理的) public class UserDaoImpl implements UserDao { public int delete() { System.out.println("删除了"); //int a=1/0; return 1; } }
测试方法:
@Test public void deletetest() { userDao.delete(); }
结果:不会输出异常的信息。
情形二:
被代理类的方法:
//编写目标类(真正被代理的) public class UserDaoImpl implements UserDao { public int delete() { System.out.println("删除了"); int a=1/0; return 1; } }
测试方法:
@Test public void deletetest() { userDao.delete(); }
结果:execution(public abstract int com.guigu.shen.anotion.UserDao.delete())方法发生了异常/ by zero18:36:25,064 INFO GenericApplicationContext:1042 - Closing [email protected]f9fdc: startup date [Mon Aug 01 18:36:07 CST 2016]; root of context hierarchy
最终通知:
@After("execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))") public void after() { System.out.print("最终通知,释放资源"); }
结果:
this is 前置方法
删除了
方法执行了0时间
最终通知,释放资源
this is afterReturning 方法
下面给出整个案例的结构图以及代码
Myspect.java是切面类
//定义一个切面类。以及Advice方法 //这个注解表明这是切面类 @Aspect public class Myspect { //我们配置一个前置方法的Advice方法,这是一个Advice方法,当然要配置切点了 @Before("execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))") public void before1(JoinPoint joinPoint) { System.out.print("this is 前置方法"); } //后置通知 @AfterReturning(value="execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))",returning="returnVal") public void afterReturning(JoinPoint joinPoint,Object returnVal) { System.out.println("this is afterReturning 方法"); System.out.println(returnVal); } //环绕通知,在方法的前后执行,在工作中可以计算方法执行的时间,性能的监控,权限的设置,缓存的实行等 @Around("execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))") public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { long begintime=System.currentTimeMillis(); Object result=proceedingJoinPoint.proceed(); long endtime=System.currentTimeMillis(); System.out.println("方法执行了"+(endtime-begintime)+"时间"); return result; } @AfterThrowing(value="execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))",throwing="e") public void afterThrowing(JoinPoint joinPoint,Exception e) { System.out.print(joinPoint.toLongString()+"方法发生了异常"+e.getMessage()); } @After("execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))") public void after() { System.out.print("最终通知,释放资源"); } }
UserDao接口类:
public interface UserDao { public int delete(); }
UserDao接口的实现类:
//编写目标类(真正被代理的) public class UserDaoImpl implements UserDao { public int delete() { System.out.println("删除了"); //int a=1/0; return 1; } }
Junit测试类:
//JUnit与Spring的整合 (用注解)@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations="classpath:applicationContext.xml") public class TestMyspect { @Autowired private UserDao userDao; @Test public void deletetest() { userDao.delete(); } public void aroundTest() { userDao.delete(); } }
ApplicationContext.xml文件:
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!-- AspectJ AOP --> <!-- 自动注解 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> <!-- xml配置目标bean和切面bean --> <bean id="UserDao" class="com.guigu.shen.anotion.UserDaoImpl"></bean> <bean id="Myspect" class="com.guigu.shen.anotion.Myspect"></bean> <!-- 流程解释: xml配置目标bean和切面bean,这样一来bean就会被加载,对象就创建好了,然后我们在之前不是配置了一个<aop:aspectj-autoproxy></aop:aspectj-autoproxy>了吗 这样就能给我们创建的UserDao和Myspect对象做代理了 --> </beans>