前言: 在上一篇中: [Spring框架]Spring AOP基础入门总结一. 中 我们已经知道了一个Spring AOP程序是如何开发的, 在这里呢我们将基于AspectJ来进行AOP 的总结和学习. 一, AspectJ的概述:
AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。
Spring为了简化自身的AOP的开发,将AspectJ拿过来作为Spring自身一个AOP的开发. 二, Spring AspectJ开发实例 2.1 开发所需jar包
2.2 AspectJ 注解开发规范
2.2.1 @AspectJ提供不同的通知类型
@Before 前置通知,相当于BeforeAdvice 在执行目标方法之前完成一个操作,获得到切入点信息. @AfterReturning 后置通知,相当于AfterReturningAdvice
1 在目标方法执行之后完成一个操作,获得方法的返回值.
2
3 @AfterReturning(value="execution(* cn.augmentum.aspectj.demo1.CustomerService+.update(..))",returning="result")
4 public void afterReturing(Object result){
5 System.out.println("后置通知============"+result);
6 }
@Around 环绕通知,相当于MethodInterceptor
1 在目标方法执行的前和执行后完成一个操作,阻止目标方法执行.
2
3 @Around(value="execution(* cn.augmentum.aspectj.demo1.CustomerService+.delete(..))")
4 public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
5 System.out.println("环绕前通知==========");
6 Object obj = joinPoint.proceed();
7 System.out.println("环绕后通知==========");
8 return obj;
9 }
@AfterThrowing抛出通知,相当于ThrowAdvice
1 在目标方法出现异常的时候,完成一个操作.获得异常信息.
2
3 @AfterThrowing(value="execution(* cn.itcast.aspectj.demo1.CustomerService+.find(..))",throwing="e")
4 public void afterThrowing(Throwable e){
5 System.out.println("异常抛出通知========="+e.getMessage());
6 }
@After 最终final通知,不管是否异常,该通知都会执行
1 在目标方法任何情况下都会执行的操作.相当于finally中的代码.
2
3 @After(value="execution(* cn.itcast.aspectj.demo1.CustomerService+.find(..))")
4 public void after(){
5 System.out.println("最终通知===========");
6 }
2.2.2 通过配置启用@AspectJ切面
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:aop="http://www.springframework.org/schema/aop"
5 xsi:schemaLocation="http://www.springframework.org/schema/beans
6 http://www.springframework.org/schema/beans/spring-beans.xsd
7 http://www.springframework.org/schema/aop
8 http://www.springframework.org/schema/aop/spring-aop.xsd">
9 <!-- 开启AspectJ自动代理-->
10 <aop:aspectj-autoproxy />
11 </beans>
2.2.3 在通知中通过value属性定义切点
通过execution函数,可以定义切点的方法切入 语法: execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>) 例如 匹配所有类public方法 execution(public * *(..)) 匹配指定包下所有类方法 execution(* cn.itcast.dao.*(..)) 不包含子包 execution(* cn.itcast.dao..*(..)) ..*表示包、子孙包下所有类 匹配指定类所有方法 execution(* cn.itcast.service.UserService.*(..)) 匹配实现特定接口所有类方法 execution(* cn.itcast.dao.GenericDAO+.*(..)) 匹配所有save开头的方法 execution(* save*(..))
2.2.4 AspectJ的切入点:
1 统一管理切入点的表达式.
2 @Pointcut(value="execution(* cn.itcast.aspectj.demo1.CustomerService+.find(..))")
3 private void myPointcut1(){} //这个类没有实际用途, 只是为了@Pointcut 注解
2.2.6 Aspect和Advisor的区别:
Advisor :传统的切面.传统切面一般都是由一个切入点和一个通知的组合. Aspect :真正意义上的切面.由多个切入点和多个通知的组合.
2.3 Spring AspctJ 基于注解模式的开发 CustomerService.java:
1 public interface CustomerService {
2
3 public void save();
4 public Integer update();
5 public void delete();
6 public void find();
7 }
CustomerServiceImpl.java:
1 public class CustomerServiceImpl implements CustomerService {
2
3 @Override
4 public void save() {
5 System.out.println("保存客户...");
6 }
7
8 @Override
9 public Integer update() {
10 System.out.println("修改客户...");
11 return 100;
12 }
13
14 @Override
15 public void delete() {
16 System.out.println("删除客户...");
17 }
18
19 @Override
20 public void find() {
21 System.out.println("查询客户...");
22 int d = 1 / 0;
23 }
24
25 }
MyAspectAnno.java:
1 /**
2 * 自定义切面类:
3 *
4 */
5 @Aspect
6 public class MyAspectAnno {
7
8 @Before(value="execution(* cn.augmentum.aspectj.demo1.CustomerService+.save(..))")
9 public void before(JoinPoint joinPoint){
10 System.out.println("前置通知============"+joinPoint);
11 }
12
13 @AfterReturning(value="execution(* cn.augmentum.aspectj.demo1.CustomerService+.update(..))",returning="result")
14 public void afterReturing(Object result){
15 System.out.println("后置通知============"+result);
16 }
17
18 @Around(value="execution(* cn.augmentum.aspectj.demo1.CustomerService+.delete(..))")
19 public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
20 System.out.println("环绕前通知==========");
21 Object obj = joinPoint.proceed();
22 System.out.println("环绕后通知==========");
23 return obj;
24 }
25
26 @AfterThrowing(value="MyAspectAnno.myPointcut1()",throwing="e")
27 public void afterThrowing(Throwable e){
28 System.out.println("异常抛出通知========="+e.getMessage());
29 }
30
31 @After(value="MyAspectAnno.myPointcut1()")
32 public void after(){
33 System.out.println("最终通知===========");
34 }
35
36 @Pointcut(value="execution(* cn.augmentum.aspectj.demo1.CustomerService+.find(..))")
37 private void myPointcut1(){}
38 }
SpringDemo.java 测试类:
1 @RunWith(SpringJUnit4ClassRunner.class)
2 @ContextConfiguration("classpath:applicationContext.xml")
3 public class SpringDemo1 {
4
5 @Resource(name = "customerService")
6 private CustomerService customerService;
7
8 @Test
9 public void demo1() {
10 customerService.save();
11 customerService.update();
12 customerService.delete();
13 customerService.find();
14 }
15 }
applicationContext.xml 配置文件:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:aop="http://www.springframework.org/schema/aop"
5 xsi:schemaLocation="
6 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
7 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
8
9 <!-- 使用注解完成AOP的开发 -->
10 <aop:aspectj-autoproxy/>
11
12 <!-- 目标对象 -->
13 <bean id="customerService" class="cn.augmentum.aspectj.demo1.CustomerServiceImpl"/>
14
15 <!-- 配置切面 -->
16 <bean id="myAspectAnno" class="cn.augmentum.aspectj.demo1.MyAspectAnno"/>
17 </beans>
2.4 Spring AspctJ 基于xml模式的开发
OrderService.java:
1 public class OrderService {
2 public void save(){
3 System.out.println("保存订单...");
4 }
5 public Integer update(){
6 System.out.println("修改订单...");
7 return 200;
8 }
9 public void delete(){
10 System.out.println("删除订单...");
11 }
12 public void find(){
13 System.out.println("查询订单...");
14 //int d = 1/ 0;
15 }
16 }
MyAspectXml.java:
1 public class MyAspectXml {
2
3 public void before(){
4 System.out.println("前置通知===========");
5 }
6
7 public void afterReturing(Object result){
8 System.out.println("后置通知==========="+result);
9 }
10
11 public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
12 System.out.println("环绕前通知==========");
13 Object obj = joinPoint.proceed();
14 System.out.println("环绕后通知==========");
15 return obj;
16 }
17
18 public void afterThrowing(Throwable e){
19 System.out.println("异常抛出通知========"+e.getMessage());
20 }
21
22 public void after(){
23 System.out.println("最终通知==========");
24 }
25 }
SpringDemo.java 测试类:
1 @RunWith(SpringJUnit4ClassRunner.class)
2 @ContextConfiguration("classpath:applicationContext.xml")
3 public class SpringDemo2 {
4
5 @Resource(name="orderService")
6 private OrderService orderService;
7
8 @Test
9 public void demo1(){
10 orderService.save();
11 orderService.update();
12 orderService.delete();
13 orderService.find();
14 }
15 }
applicationContext.xml 配置文件:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:aop="http://www.springframework.org/schema/aop"
5 xsi:schemaLocation="
6 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
7 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
8
9 <!-- 配置目标类 -->
10 <bean id="orderService" class="cn.augmentum.aspectj.demo2.OrderService"></bean>
11
12 <!-- 配置切面 -->
13 <bean id="myAspectXml" class="cn.augmentum.aspectj.demo2.MyAspectXml"></bean>
14
15 <!-- AOP的配置 -->
16 <aop:config>
17 <aop:pointcut expression="execution(* cn.augmentum.aspectj.demo2.OrderService.save(..))" id="pointcut1"/>
18 <aop:pointcut expression="execution(* cn.augmentum.aspectj.demo2.OrderService.update(..))" id="pointcut2"/>
19 <aop:pointcut expression="execution(* cn.augmentum.aspectj.demo2.OrderService.delete(..))" id="pointcut3"/>
20 <aop:pointcut expression="execution(* cn.augmentum.aspectj.demo2.OrderService.find(..))" id="pointcut4"/>
21 <aop:aspect ref="myAspectXml">
22 <aop:before method="before" pointcut-ref="pointcut1"/>
23 <aop:after-returning method="afterReturing" pointcut-ref="pointcut2" returning="result"/>
24 <aop:around method="around" pointcut-ref="pointcut3"/>
25 <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="e"/>
26 <aop:after method="after" pointcut-ref="pointcut4"/>
27 </aop:aspect>
28 </aop:config>
29 </beans>
OK. 到了这里Spring 基于AOP的开发也总结完了, 学习之路漫漫, 谨以此记录成长的过程!