Spring学习笔记(三) AOP_annotation,AOP_XML

在学习课程以前,听说AOP有种很神秘的感觉,好像很好深的技术。其实原理很简单,使用动态代理的方式给程序增加逻辑。与此相似的有struts2中的filter拦截器。

再讲AOP之前先把需求说一下: 同Spring学习笔记(一)IoC中的需求一样,只不过要在save()方法前后增加日志log的记录。

不使用AOP的方式可以有两种实现思路:

1—>使用继承的的方式,把有save方法的类继承,然后在增加log逻辑

2—>使用组合的方式,即增加一个记录逻辑的类,分别有在save()方法前save()方法后记录日志的功能,然后把这两个类组合到一起

虽然上面两种方式都能解决我们的需求,但是一个问题来了:如果有500个更甚至1000各类中的方法需要增加逻辑,使用继承的方法和组合的方法的弊端就出来了。一方面会增加海量的代码量。另一方面,会使整个程序的可读性变差。程序员在写程序的时候不能专注于业务逻辑,还要专注于维护逻辑,增加程序员的逻辑压力,从而用于调试的时间会增多。

从而,出现了AOP,来解决这类问题。Spring中的AOP实现原理使用的是JavaJDK中的动态代理。

AOP_annotation

AOP_annotation环境搭建

  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/aop
  7.            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
  8.     <aop:aspectj-autoproxy />
  9. </beans>

增加AOP的xml命名空间以及xsd路径设置。最重要的是增加<aop:aspect-autoproxy>

Aspectj是专门用来实现动态代理的类库,spring中的AOP使用的是aspectj.jar实现的。需要在库中增加aspectj的类库。

@Aspect,@Before

@Aspect:即标注这个类为切面类,是增加的逻辑的那个类。放在我们的需求里面,log记录方法应写在被@Aspect标注的类

@Before:切入点的逻辑,即是在增加save()方法前面执行

Execution…:切入点语法

  1. @Aspect
  2. @Component
  3. public class LogInterceptor {
  4.   @Before("execution(* com.xxxx.dao.impl.UserDAOImpl.save(com.xxxx.model.User))")
  5.    public void before() {
  6.       System.out.println("method before");
  7.    }
  8. }

其中@Before口号中的execution()是注册那个保重的那个类中的那个方法加入切入逻辑。

@PointCut

  1. @Aspect
  2. @Component
  3. public class LogInterceptor {
  4.    @Pointcut("execution(public * com.xxxx.service..*.add(..))")
  5.    public void myMethod(){};
  6. }

@PointCut:切入点集合。即对com.xxx.service包中的类中任何返回值的add()方法(add()方法的参数任意)增加切入逻辑    

这种给相关方法加入切入逻辑的动作又叫作织入(Weave),切入点语法为execution的为aspectj的织入语法。Spring AOP也有自己的语法,到时候查阅参考文档吧!

@AfterReturning,@AfterThrowing,@After(finally)

这些方法的使用跟@Before类似

@Around

  1. @Aspect
  2. @Component
  3. public class LogInterceptor {
  4.    @Pointcut("execution(public * com.bjsxt.service..*.add(..))")
  5.    public void myMethod(){};
  6.    @Around("myMethod()")
  7.    public void aroundMethod(ProceedingJoinPoint pjp) throws Throwable {
  8.       System.out.println("method around start");
  9.       pjp.proceed();
  10.       System.out.println("method around end");
  11.    }
  12. }

其中有两个知识点

    1à这一点在刚才说@PointCut是没有说明,就是呗@PointCut标记的方法名字myMethod为@PointCut所标记的那些切入点方法集合的表示符号。举个例子,

int myMethod=@PointCut

    2à@around要使用pjp.proceed()执行切入点save()方法

AOP_XML

  1. <bean id="logInterceptor" class="com.bjsxt.aop.LogInterceptor" ></bean>
  2. <aop:config>
  3.     <aop:aspect id="logAspect" ref="logInterceptor" >
  4.         <aop:pointcut id="myMethod" expression="execution(public void com.bjsxt.dao.impl.UserDAOImpl.save(com.bjsxt.model.User))"></aop:pointcut>
  5.         <aop:before method="before" pointcut-ref="myMethod"></aop:before>
  6.       <aop:after-returning method="myafter" pointcut="execution(public void com.bjsxt.dao.impl.UserDAOImpl.save(com.bjsxt.model.User))">
  7.     </aop:aspect>
  8. </aop:config>

上述代码写了AOP中XML方式书写的格式,其中pointcut的三种写法都在上面4,5,6行中。

原文地址:https://www.cnblogs.com/wenlonghor/p/3295863.html