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接口

        

 

posted @ 2015-06-07 18:45  好运的炯哥哥  阅读(260)  评论(0编辑  收藏  举报