• SpringAop代理模式笔记


    aop:面向切面编程(分为代理类和目标类)
      需求:把原本要放一起运行的代码由于不符合设计 对他们进行进行解耦,在运行时在动态的结合在一起.

      核心原理:就是利用了(默认为)jdk的动态和cglib的动态代理
      动态代理分为:dynamic和cglib

      <bean name="beforeAdvice" class="com.briup.aop.before.BeforeAdvice">
        <!-- 注入切面类 -->
        <property name="logger" ref="logger"></property>
      </bean>


      xml:标签中的命名空间中的声明中后的url路径只起唯一标识作用 jtsl标签同理  普通代理模式:

        1)静态代理(通常用于学习,在程序运行前,代理类的.class文件就已经存在了):
          代理类和委托类实现同一接口,重写接口的方法,里面加入委托类的相同方法实现,以及需要新加入的实现,(在放入ioc中拿取)
        2)动态代理:(在程序运行时,代理类是运用了反射技术或字节码技术动态创建而成的)
          1.jdk自带的动态代理:(用于实现了接口的类 具体通过实现InvocationHandler接口的类 中的invoke方法中在实现委托类的方法的基础上在加入新的需求,),

            为什么委托类一定要实现接口呢,因为代理类已经默认继承了Proxy类,因为java是单继承的,又需要返回相同的数据类型(所以需要接口来充当父类引用)
          2.cglib代理(用于没有实现接口的类,通过生成子类, 调用委托类的方法时,加入一些需求)
          aop(面向切面编程:将需求变成切面类(aspect),委托类中的方法变成连接点(joinpoint);通知/拦截器(advice)控制织入(wave)到方法执行前后位置或抛异常的时候;增强器(adivsor用来删选那些方法为连接点)(没有增强器时,默认委托类中的所有方法都为连接点),切入点(pointCut :为一组连接点的集合

    AOP的概念:

        AOP          面向切面编程

        aspect        切面/切面类(要切入的内容)

        joinPoint    连接点
                在spring的aop中只有 类中的方法 可以做连接点,每一个方法都可以是一个连接点.
            
        pointCut    切入点
                一组连接点的集合

        advice        通知/拦截器 (控制织入地点)
                用来控制切面类将来到底是织入到切入点的前面、后面或者是抛异常的时候。

        adivsor        增强器
                用来筛选类中的哪些方法是我们的连接点(哪些方法需要被拦截).

        target        目标对象

        proxy        代理对象

        wave        织入

    advice(通知)的类型:

            前置通知(Before advice):
                在某些连接点(方法,是接口中的方法)(join point)之前执行的通知

            返回后通知(After returning advice):
                在某些连接点(join point)正常完成后执行的通知(方法正常结束,没有异常)

            抛出异常后通知(After throwing advice):
                在某些连接点(join point)抛出异常退出时执行的通知

            后通知(After (finally) advice):
                当某些连接点(join point)退出的时候执行的通知

            环绕通知(Around Advice):
                包围一个连接点(join point)的通知,例如事务的处理,就需要这样的通知,因为事务需要在方法前开启,在方法后提交,以及方法抛出异常时候回滚

    注:在spring中,连接点(join point)指的就是方法

    1,aop:config标签(':' 前面的是命名空间,区分标签的,避免命名冲突)

    使用aop的专用标签来完成相关的配置.
    其中主要表现是使用expression的操作:

    expression = "execution(public * com.briup.aop.service.*.*(..))"

    引号里面就是用表达式的方式来定义切入点,只要是符合这个表达式要求的,该方法就是连接点,连接点的集合就是我们要定义的切入点

    从左至右:第一个*:方法的返回类型不限

         第二个*:表示包中任意一个类

        第三个*:类中任意一个返回类型的方法

        (..) 匹配了一个接受任意数量参数的方法

        (*,String) 匹配了一个接受两个参数的方法,第一个可以是任意类型,第二个则必须是String类型

        () 匹配了一个不接受任何参数的方法

    2,使用注解配置AOP,就可以去掉xml中的aop标签配置

     @Component
        @Aspect
        public class AnnotationHandler {
            /*
             * 在一个方法上面加上注解来定义切入点
             * 这个切入点的名字就是这个方法的名字
             * 这个方法本身不需要有什么作用
             * 这个方法的意义就是:给这个 @Pointcut注解一个可以书写的地方
             * 因为注解只能写在方法、属性、类的上面,并且方法名作为切入点的名字
             * */
            @Pointcut("execution(public * com.briup.aop.service..*.*(..))")
            public void myPointCut(){}

      //切入点方法执行前调用

      @Before("myPointCut()")
            public void beforeTest(JoinPoint p){
                System.out.println(p.getSignature().getName()+" before...");
            }

      //切入点方法执行期间抛出异常的时候,会调用这个

      @AfterThrowing(value="myPointCut()",throwing="ex")
            public void throwingTest(JoinPoint p,Exception ex){
                System.out.println(p.getSignature().getName()+" is throwing..."+ex.getMessage());
                
            }
            
        }

      xml配置:
        <aop:aspectj-autoproxy/>
        <context:component-scan base-package="com.briup.aop"/>

    注意:<aop:aspectj-autoproxy proxy-target-class="true"/>这样配置则是强制使用CGLIB进行代理

    aop普通手动(org.springframework.aop.framework.ProxyFactoryBean)代理工厂:
    <bean name="proxy"  class="org.springframework.aop.framework.ProxyFactoryBean">
      <!-- 注入目标对象 -->
      <property name="target" ref="target"></property>

      <!-- 注入目标对象所实现的接口 可以有多个接口 -->
      <property name="proxyInterfaces">
        <list>
          <value>com.briup.aop.service.IAccountService</value>
        </list>
      </property>

      <!-- advice表示拦截委托类里的所有方法,-->
      <!-- 配置advisor 增强器-->
      <!-- 作用:筛选要拦截(要代理)的方法 -->
      <bean name="advisor"
        class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <!-- 注入advice-->
        <property name="advice" ref="beforeAdvice"></property>
        <!-- 注入需要被拦截的目标对象中的方法(连接点) -->
        <property name="patterns">
          <list>
            <value>.*bankAction</value> 单个字符出现0到多次
          </list>
        </property>
      </bean>
      <!-- 配置增强器可指定拦截委托类中的指定方法-->

      <!-- 注入advice 可以有多个 也可直接注入advisor-->
      <property name="interceptorNames">
        <list>
          <value>throwAdvice</value>
        </list>
      </property>
    </bean>


    aop自动代理工厂:
      1).通过拦截器指定需要拦截的具体方法,
        <!-- 配置advisor -->
        <!-- 作用:筛选要拦截的方法 -->
        <bean name="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
          <!-- 注入advice -->
          <property name="advice" ref="beforeAdvice"></property>
          <!-- 注入需要被拦截的目标对象中的方法 -->
          <property name="patterns">
            <list>
              <value>.*bankAction</value>
            </list>
          </property>
        </bean>


      2)配置自动代理工厂,
        <!-- 配置代理对象 -->
        <!-- 这里使用自动代理的方式 autoproxy -->
        <!-- 注意:这不是一个工厂类,所以不能用过proxy来拿代理对象 -->
        <bean name="proxy"
          class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
        </bean>
      3)直接通过委托类名拿到具体的代理对象

    2.AutoProxyByName 通过名字进行自动代理:BeanNameAutoProxyCreator类的使用
      1)配置拦截器(有无都没关系)
        <!-- 配置advisor -->
        <!-- 作用:筛选要拦截的方法 -->
        <bean name="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <!-- 注入advice -->
          <property name="advice" ref="beforeAdvice"></property>
          <!-- 注入需要被拦截的目标对象中的方法 -->
          <property name="patterns">
            <list>
              <value>.*bankAction</value>
            </list>
          </property>
        </bean>


      2)配置自动代理工厂
        <!-- 配置代理对象 -->
        <!-- 这里使用自动代理的方式 autoproxybyname -->
        <bean name="proxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">

        <!-- 注入需要被代理的对象名字 -->
          <property name="beanNames">
            <list>
              <value>target</value>
              <value>target2</value>
              <value>dao</value>
              <value>service*</value>
            </list>
          </property>

          <!-- 注入advice或者advisor -->
          <property name="interceptorNames">
            <list>
              <value>advisor</value>
            </list>
          </property>
       </bean>
    3)也是直接通过目标对象名获取代理对象

    aop:config标签
    <!-- 配置aop的代理 -->
    <aop:config>
      <!-- 定义一个切入点 并给切入点起名为myPointCut -->
      <!-- 切入点是一组连接点的集合 -->
      <aop:pointcut expression="execution(public * com.briup.aop.service.*.*(..)) or execution(public * com.briup.aop.service.*.*(..)) or......" id="myPointCut"/>

      <!-- 定义哪一个advice在哪一个切入点上面起作用 -->
      <aop:advisor advice-ref="beforeAdvice" pointcut-ref="myPointCut" />
    </aop:config>

    注意:<aop:config proxy-target-class="true"> 如果这样配置则是强制使用CGLIB方式进行代理


    <!-- aop:aspect标签:定义切面类 把类中的方法(相当于advice)分别织入到切入点中的各个位置 -->
    <!-- 配置切面类 -->
      <bean name="handler" class="com.briup.aop.xml.XmlHandler"></bean>
      <aop:aspect id="aspect" ref="handler">
      <!-- 表示beforeAdvice会把切面类handler中的beforeTest方法织入到名字叫myPointCut的切入点前面 -->
      <aop:before method="beforeTest" pointcut-ref="myPointCut"/>

    <!-- after表示不管方法是否正常结束都会起作用 -->
      <aop:after method="afterTest" pointcut-ref="myPointCut"/>

    <!-- after-returning表示方法正常结束才会起作用(抛异常时候不起作用) -->
      <aop:after-returning method="afterReturningTest" pointcut-ref="myPointCut"/>

      <aop:around method="aroundTest" pointcut-ref="myPointCut"/>

    <!-- throwing="ex"表示throwingTest方法中接收异常对象的名字一定要是ex -->
      <aop:after-throwing method="throwingTest" pointcut-ref="myPointCut" throwing="ex"/>
      </aop:aspect>

  • 相关阅读:
    !!“理都懂”为什么“然并卵”?
    启明创投甘剑平:破解独角兽公司的基因密码
    任正非:华为3年前应该快垮了
    C语言 · 8皇后问题改编
    C语言 · 数的划分
    C语言 · 8皇后问题
    C语言 · 数字黑洞
    C语言 · FBI树
    C语言 · 超级玛丽
    C语言 · 数的划分
  • 原文地址:https://www.cnblogs.com/nyhhd/p/12547234.html
Copyright © 2020-2023  润新知