zoukankan      html  css  js  c++  java
  • Spring-AOP

    概述

        1、AOP即Aspect-Oriented Programming,他是面向切面编程的核心思想。

        2、AOP与OOP即面向对象的编程语言,不相冲突,他们是两个相辅相成的设计模式。

        3、Spring的容器并不依赖于AOP。

    AOP简介

        1。AOP专业术语:

          Cross-cutting concern:系统层面上的服务穿插到业务逻辑的处理流程之中

          Aspect:当需要时,将其放到应用程序之上,不需要时,将其从应用程序中解脱出来。

          Advice:Aspect的具体实现。

          Joinpoint:连接点,Aspect在应用程序执行时,加入业务流程的时机。

          pointcut:切入点,通过定义pointcut,可以指定某个Aspect在哪些Joinpoint时,被穿插至应用程序之上。

          target:是一个目标对象,一个advice被应用的对象和目标对象。

          instruction:为已编写、编译完成的类,在执行时期动态的加入一些方法,而不用修改和增加任何代码。

          weave:即织入,被应用到对象之上的过程,AOP织入有3个状态:编译,类加载,执行时期

        2、Spring对AOP的支持

          1、纯jiava语言编写。

          2、定义pointcuts可以使用配置文件。

          3、不支持属性成员的joinpoints。

        3、Spring创建Advice

           一:Before Advice:会在目标对象traget的方法执行之前被调用

            通过实现MethodBeforeAdvice接口来实现:

            实现步骤:

            1:创建代理对象接口类

    public interface Ihello {
        public void saychina(String str);
        public void meiguosay(String str);
    
    }

            2:创建目标对象类,并实现代理对象接口类。

    public class hello implements Ihello {
    
        public void saychina(String str){
            System.out.println("你好中国人"+str);
    
        }
    
        public void meiguosay(String str) {
            System.out.println("你好美国人"+str);
            
        }
    
    }

            3:创建一个Advice类,并实现MethodBeforeAdvice接口,重写方法

    import java.lang.reflect.Method;
    
    import org.springframework.aop.MethodBeforeAdvice;
    
    
    public class SaybeforeAdvice implements MethodBeforeAdvice {
    
        @Override
        public void before(Method arg0, Object[] arg1, Object arg2)
                throws Throwable {
            System.out.println("在方法调用之前做的事情!");
    
        }
    
    }

            4:创建applicationContext.xml,并配置

    <!-- 建立目标对象实例 -->
        <bean id="hello" class="hello"></bean>
        <!-- 建立Advice实例 -->
        <bean id="sab" class="SaybeforeAdvice"></bean>
        <!-- 建立代理实例 -->
        <bean id="hellopoxy" class="org.springframework.aop.framework.ProxyFactoryBean">
            <!-- 设定代理的接口 -->
            <property name="proxyInterfaces">
                <value>Ihello</value>
            </property>
            <!-- 设定目标对象 实例-->
            <property name="target">
                <ref bean="hello"/>
            </property>
            <!-- 建立Advice实例 -->
            <property name="interceptorNames">
                <list>
                    <value>sab</value>
                </list>
            </property>
        </bean>

                   二:afterAdvice:afterReturning

              1、会在目标方法被执行之后调用。

              2、通过实现afterReturningAdvice接口来实现。并重写public void afterReturning(Object arg0, Method arg1, Object[] arg2,

    Object arg3) throws Throwable {}方法

    import java.lang.reflect.Method;
    
    import org.springframework.aop.AfterReturningAdvice;
    
    
    public class afterAdvice implements AfterReturningAdvice {
    
        @Override
        public void afterReturning(Object arg0, Method arg1, Object[] arg2,
                Object arg3) throws Throwable {
            System.out.println("在目标对象执行完之后调用");
    
        }
    
    }
    <!-- 建立目标对象实例 -->
        <bean id="hello" class="hello"></bean>
        <!-- 建立Advice实例 -->
        <bean id="sab" class="SaybeforeAdvice"></bean>
        <bean id="aab" class="afterAdvice"></bean>
        <!-- 建立代理实例 -->
        <bean id="hellopoxy" class="org.springframework.aop.framework.ProxyFactoryBean">
            <!-- 设定代理的接口 -->
            <property name="proxyInterfaces">
                <value>Ihello</value>
            </property>
            <!-- 设定目标对象 实例-->
            <property name="target">
                <ref bean="hello"/>
            </property>
            <!-- 建立Advice实例 -->
            <property name="interceptorNames">
                <list>
                    <value>sab</value>
                    <value>aab</value>
                </list>
            </property>
        </bean>

        三:Around Advice:在目标对象方法执行前后都执行

          要实现MethodInterceptor接口并重写public Object invoke(MethodInvocation arg0) throws Throwable {

            //目标对象执行之前执行的代码

            ?????

            arg0.proceed();

            //目标对象执行之后执行的代码块

            ????

            //该方法有返回值

            return Object;

    }

    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    
    
    public class SayAroundAdive implements MethodInterceptor {
    
        @Override
        public Object invoke(MethodInvocation arg0) throws Throwable {
            System.out.println("开始之前奏");
            arg0.proceed();
            System.out.println("完事之后的服务");
            return null;
        }
    
    }

        四:throw Advice:异常发生的时候,通知某个服务对象做处理,只是提示异常信息,不会处理异常

          实现ThrowsAdvice接口,该接口没有方法,可自定义方法。

          可在测试目标对象方法中抛出自定义异常:Throw new exception("发生异常");  

          

    public class SayThrowAdvice implements ThrowsAdvice {
        public void afterThrowing(Method method,Object[]objs,Object target,Throwable ta){
            //输出 异常的 内容 和 抛出 异常的 方法 
            System.out.println("exception happened"+ta+"and was thrown in"+method);
            
        }
    
    }

                配置Spring配置文件

    <!-- 建立目标对象实例 -->
        <bean id="hello" class="hello"></bean>
        <!-- 建立Advice实例 -->
            <!-- befoer Advice -->
        <bean id="sab" class="SaybeforeAdvice"></bean>
            <!-- after Advice -->
        <bean id="aab" class="afterAdvice"></bean>
            <!--        Around Advice -->
        <bean id="srb" class="SayAroundAdive"></bean>
            <!-- throwAdice -->
        <bean id="tad" class="SayThrowAdvice"></bean>
        <!-- 建立代理实例 -->
        <bean id="hellopoxy" class="org.springframework.aop.framework.ProxyFactoryBean">
            <!-- 设定代理的接口 -->
            <property name="proxyInterfaces">
                <value>Ihello</value>
            </property>
            <!-- 设定目标对象 实例-->
            <property name="target">
                <ref bean="hello"/>
            </property>
            <!-- 建立Advice实例 -->
            <property name="interceptorNames">
                <list>
                    <!-- <value>sab</value>
                    <value>aab</value>
                    <value>srb</value>
                     -->
                     <value>tad</value>
                    
                </list>
            </property>
        </bean>

        五:基于xml Schema创建Advice

             目标对象类,代理类,Adivce类(可自定义,无需实现接口)

             优点:简化代码实现,容易对应用程序进行维护,所有元素都定义在<aop:config>标签元素中

    import java.lang.reflect.Method;
    
    import org.springframework.aop.MethodBeforeAdvice;
    
    
    public class BeforeAdive {
    
        
        public void before(){
            System.out.println("之前的事情!");
    
        }
    
    }

            <aop:config>标签

              可包含多个切面(aspect),切入点(pointcut),advice等标签元素

              <aop:aspect>标签元素

              定义一个切面

              <aop:pointcut>:定义切入点的信息。

                experssion是执行的表达式:常用形式1、*符号:表示匹配任意的返回类型

                              2、():表示匹配一个不带参数的方法

                              3、(..):表示匹配了一个带任意参数的方法

             <aop:after>定义一个after Advice

             <aop:before>定义一个before Advice

             <aop:around>定义一个Around Advice

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 需先在beans声明xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"
     -->
    <beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
            ">
            <!-- adivice类实例 -->
        <bean id="beforeAdvice" class="BeforeAdive" ></bean>
         <!-- 目标对象实例 -->
        <bean id="hello" class="hello" ></bean>
        <aop:config >
            <!-- 定义切入点 -->
            <aop:pointcut expression="execution(public void *(..))" id="helloPointcut" />
            <!-- 定义切面 -->
            <aop:aspect ref="beforeAdvice" >
                <!-- 定义advice类型,方法,和关联类 -->
                <aop:before method="before" pointcut-ref="helloPointcut" />
            </aop:aspect>
        </aop:config>
    
    </beans>

       六、基于annotation创建Advice

       七、定义pointcut、advice

          Spring中的pointcutAdvisor将pointcut和advice结合成一个对象

              1、NameMatchMethodPointcutAdvisor():匹配方法名

              2、RegexpMethodPointcutAdvisor():用正则表达式的方式定义(静态pointcut实例)

              实例应用xml代码

    <!-- 建立目标对象实例 -->
        <bean id="hello" class="hello"></bean>
        <!-- 建立Advice实例 -->
            <!-- befoer Advice -->
        <bean id="sab" class="SaybeforeAdvice"></bean>
            <!-- after Advice -->
        <bean id="aab" class="afterAdvice"></bean>
            <!--        Around Advice -->
        <bean id="srb" class="SayAroundAdive"></bean>
            <!-- throwAdice -->
        <bean id="tad" class="SayThrowAdvice"></bean>
        <!-- 建立Spring内置pointcutAdvisor:NameMatchMethodPointcutAdvisor -->
        <bean id="helloPerson" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
            <!-- 制定匹配的方法名 :以say开头的方法-->
            <property name="mappedName">
                <value>say*</value>
            </property>
            <!-- 制定与之关联的advice -->
            <property name="advice">
                <ref bean="sab"/>
            </property>
        </bean>
        <!-- 建立Spring内置pointcutAdvisor:RegexpMethodPointcutAdvisor -->
        <bean id="helloPerson2" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <!-- 制定匹配的正则表达式 -->
            <property name="pattern">
                <value>.*say.*</value>
            </property>
            <!-- 制定与之关联的advice -->
            <property name="advice">
                <ref bean="aab"/>
            </property>
        </bean>
        <!-- 建立代理实例 -->
        <bean id="hellopoxy" class="org.springframework.aop.framework.ProxyFactoryBean">
            <!-- 设定代理的接口 -->
            <property name="proxyInterfaces">
                <value>Ihello</value>
            </property>
            <!-- 设定目标对象 实例-->
            <property name="target">
                <ref bean="hello"/>
            </property>
            <!-- 建立Advice实例 -->
            <property name="interceptorNames">
                <list>
                     <value>helloPerson</value>
                    <value>helloPerson2</value>
                    <!--<value>srb</value>
                    
                     <value>tad</value> -->
                    
                </list>
            </property>
        </bean>
    
    
    </beans>

        八、动态代理

               1、通过动态的代理模式,在目标对象的方法调用前后,插入相应的处理代码

          2、Spring所实现的动态代理,其内置的aop默认使用动态代理模式来实现。

          3、不必为特定的对象或者方法编写实现特定功能的代理对象。

          3、一个处理者类必须实现invocationHandler接口

            

  • 相关阅读:
    MySQL 存储过程
    linux iptables 相关设置
    Ubuntu iptables 设置
    Mac OS 10.12
    解决:cc1.exe: sorry, unimplemented: 64-bit mode not compiled in
    go get golang.org/x/net 安装失败的解决方法!
    Ubuntu16.04
    Ubuntu16.04
    Ubuntu16.04
    在Ubuntu16.04里面安装Gogland!
  • 原文地址:https://www.cnblogs.com/hjiongjiong/p/4558868.html
Copyright © 2011-2022 走看看