Spring AOP原理以及Spring源码实现分析

1.从字面的意思理解AOP.?

    面向切面编程(全称Aspect Oriented programing),通过预编译的方式和动态代理(运行期)实现程序功能的一种方式,AOP      是对OOP(面向对象编程)的一种扩充。

2.AOP解决了什么问题?

   在一个完善的系统中,我们常用到的监听、日志、权限、事务、缓存等等操作,在这些业务场景中我们需要对多个方法或者对多个动作调用之前或者调用之后进行我们想要的操作(可能为封装好方法的一个类),例如:我们需要记录我们操作的日志。什么人在什么时候调用了什么方法做了什么事(张三在2018-05-21在系统中注册了一个的系统登录的用户,张三在2018-05-21在系统中删除了一个的系统登录的用户) ,诸如此类的情况,如果我们每一个操作都添加一个操作记录,我们需要花大量的时间记录操作,代码会非常冗余,也不利于后期的维护。这时我们就想到是否能有一个简单的方式方法可以简化我们操作,让我们不需要每一个操作都去单据加一个操作日志的功能,顺着这个思路,在一个系统中如果有一个切入点(对方法而言,我们一般不需要对所有方法都进行日志操作,我们只需要对特定的方法进行相关的日志记录,我们可以自定义一个规则让我们执行特定的方法的前后去执行我们想要做的事),我们就可以减少很多我们不必要的操作。

<bean class="org.springframework.orm.hibernate4.HibernateTransactionManager" id="TransactionManager">
         <property name="sessionFactory" ref="sessionFactory"></property>
   </bean>
  
   <tx:advice id="txAdvice" transaction-manager="TransactionManager">
     <tx:attributes>
         <tx:method name="add*" propagation="REQUIRED"/>
         <tx:method name="upp*" propagation="REQUIRED"/>
         <tx:method name="del*" propagation="REQUIRED"/>
         <tx:method name="*" read-only="true"/>
     </tx:attributes>
   </tx:advice>
   
   
   <aop:config>
      <aop:pointcut expression="execution(* com.svse.impl.*.*(..))" id="allmethods"/>
      <aop:advisor advice-ref="txAdvice" pointcut-ref="allmethods"/>
    </aop:config>
    
    <context:component-scan base-package="com.svse"></context:component-scan>

3.Spring AOP 中的关键词

        3.1 什么是切点?

                   通过正则表达式进行匹配的点(Spring 中有一个包专门是对expression进行解析,转化为对应的文件)

<aop:pointcut expression="execution(* com.svse.impl.*.*(..))" id="allmethods"/>

 

        3.2什么是切面?

                    就是我们要对当前方法执行的前后进行的操作,把这些操作封装成一个类。通过配置Bean的方式进行注入

         

// ClassPathApplicationContext.xml的配置切面
 <bean id="xmlAopDemoUserLog" class="com.svse.util.XmlAopDemoUserLog"></bean>

//插入具体的操作逻辑的类(我们的切面)

public class XmlAopDemoUserLog {
//    方法执行前通知
    public void beforeLog() {
        System.out.println("开始执行前置通知  日志记录");
    }
//    方法执行完后通知
    public void afterLog() {
        System.out.println("开始执行后置通知 日志记录");
    }
//    执行成功后通知
    public void afterReturningLog() {
        System.out.println("方法成功执行后通知 日志记录");
    }
//    抛出异常后通知
    public void afterThrowingLog() {
        System.out.println("方法抛出异常后执行通知 日志记录");
    }

//    环绕通知
    public Object aroundLog(ProceedingJoinPoint joinpoint) {
        Object result = null;
        try {
            System.out.println("环绕通知开始 日志记录");
            long start = System.currentTimeMillis();

            //有返回参数 则需返回值
            result =  joinpoint.proceed();

            long end = System.currentTimeMillis();
            System.out.println("总共执行时长" + (end - start) + " 毫秒");
            System.out.println("环绕通知结束 日志记录");
        } catch (Throwable t) {
            System.out.println("出现错误");
        }
        return result;
    }
}

        3.3什么是通知?

将横向业务内容也即横切性关注点的内容封装为一个方法,这个方法称为“通知”advice

,它可以放在主方法的前面(比如User里面的add方法是主方法而checkSecurity可以放在add方法前面后面等,均可)也可以放在后面。除此外还有异常通知、环绕通知和最终通知。(上面切面里面的具体方法)

被方法化的横切性关注点称为通知,它可以放在前后等多个地方。

        3.4.什么是连接点?

               就是那些被拦截到的点(被拦截的方法),spring这些点就是方法。也就是主线业务中的主要方法,每一

               方法就是一个连接点,比如User类的CRUD四个方法,就是4个连接点。

        3.5.什么是织入?

              将aspect运用到代理的目标对象上并导致proxy创建的过程称为织入。

4.AOP的代码实现原理

      AOP的实现实际上是用动态代理实现的,动态代理的实现又主要分为两种 :

              第一种、jdk (proxy implements InvocationHandler)).

              第二种 cglib(proxy extends cglib)

      哪什么时候用jkd,什么时候用cglib?

         如果目标对象的代理至少实现了一个接口,那么就用JDK动态代理,所有由目标对象实现的接口将全部都被代理。如果目     标 对象没有实现任何接口,那么就用CGLIB代理。

 

 

 

 

 

         

 

    

    原文作者:AOP
    原文地址: https://blog.csdn.net/qq_36975405/article/details/82079969
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞