spring aop用法

springAOP(面向切面编程)在我们项目中是经常要用到的 下面说一下怎么用 也是我们最常用的方法.

与大多数技术一样,AOP已经形成了自己的术语。描述切面的常用术
语有通知(advice)、切点(pointcut)和连接点(join point

 

通知(Advice)切面也有目标——它必须要完成的工作。在AOP术语中,切面的工作被称为通知

通知定义了切面是什么以及何时使用。除了描述切面要完成的工作,
通知还解决了何时执行这个工作的问题。它应该应用在某个方法被调
用之前?之后?之前和之后都调用?还是只在方法抛出异常时调用?

Spring切面可以应用5种类型的通知:
前置通知(Before):在目标方法被调用之前调用通知功能;
后置通知(After):在目标方法完成之后调用通知,此时不会关
心方法的输出是什么;
返回通知(After-returning):在目标方法成功执行之后调用通
知;
异常通知(After-throwing):在目标方法抛出异常后调用通知;
环绕通知(Around):通知包裹了被通知的方法,在被通知的方
法调用之前和调用之后执行自定义的行为。

 

连接点(Join point:连接点是在应用执行过程中能够插入切面的一个点。这个
点可以是调用方法时、抛出异常时、甚至修改一个字段时。切面代码
可以利用这些点插入到应用的正常流程之中,并添加新的行为

 

切点(Poincut:一个切面并不需要通知应用的所有连接点。切点有助于

缩小切面所通知的连接点的范围。
如果说通知定义了切面的什么何时的话,那么切点就定义
何处。切点的定义会匹配通知所要织入的一个或多个连接点。我
们通常使用明确的类和方法名称,或是利用正则表达式定义所匹配的
类和方法名称来指定这些切点。有些AOP框架允许我们创建动态的切
点,可以根据运行时的决策(比如方法的参数值)来决定是否应用通

切面(Aspect)切面是通知和切点的结合。通知和切点共同定义了切面的全部内容
——它是什么,在何时和何处完成其功能

 

引入(Introduction:引入允许我们向现有的类添加新方法或属性。例如,我们可以创建一
Auditable通知类,该类记录了对象最后一次修改时的状态。这
很简单,只需一个方法,setLastModified(Date),和一个实例
变量来保存这个状态。然后,这个新方法和实例变量就可以被引入到
现有的类中,从而可以在无需修改这些现有的类的情况下,让它们具
有新的行为和状态。


织入(Weaving:织入是把切面应用到目标对象并创建新的代理对象的过程。切面在指
定的连接点被织入到目标对象中。在目标对象的生命周期里有多个点
可以进行织入:
编译期:切面在目标类编译时被织入。这种方式需要特殊的编译
器。AspectJ的织入编译器就是以这种方式织入切面的。
类加载期:切面在目标类加载到JVM时被织入。这种方式需要特
殊的类加载器(ClassLoader),它可以在目标类被引入应用
之前增强该目标类的字节码。AspectJ 5的加载时织入(load-time
weavingLTW)就支持以这种方式织入切面。
运行期:切面在应用运行的某个时刻被织入。一般情况下,在织
入切面时,AOP容器会为目标对象动态地创建一个代理对象。
Spring AOP就是以这种方式织入切面的。

 

要掌握的新术语可真不少啊可以根据下面两张图理解一下

 

 

 

 

SpringAOP的支持 并不是所有的AOP框架都是相同的,它们在连接点模型上可能有强弱
之分。有些允许在字段修饰符级别应用通知,而另一些只支持与方法
调用相关的连接点。它们织入切面的方式和时机也有所不同。但是无
论如何,创建切点来定义切面所织入的连接点是AOP框架的基本功
 SpringAspectJ项目之间有大量的协作,而且SpringAOP
支持在很多方面借鉴了AspectJ项目

Spring提供了4种类型的AOP支持:

基于代理的经典Spring AOP;
POJO切面;
@AspectJ注解驱动的切面;
注入式AspectJ切面(适用于Spring各版本)。

前三种都是Spring AOP实现的变体,Spring AOP构建在动态代理基础
之上,因此,Spring对AOP的支持局限于方法拦截

Spring的经典AOP编程模型并不怎么
样。当然,曾经它的确非常棒。但是现在Spring提供了更简洁和干净
的面向切面编程方式。引入了简单的声明式AOP和基于注解的AOP
后,Spring经典的AOP看起来就显得非常笨重和过于复杂,直接使用
ProxyFactory Bean会让人感觉厌烦

借助Springaop命名空间,我们可以将纯POJO转换为切面。实际
上,这些POJO只是提供了满足切点条件时所要调用的方法。遗憾的
是,这种技术需要XML配置或者Java配置方式,但这的确是声明式地将对象转换为切面
的简便方式

 

Spring通知是Java编写的
Spring所创建的通知都是用标准的Java类编写的。这样的话,我们就
可以使用与普通Java开发一样的集成开发环境(IDE)来开发切面。
而且,定义通知所应用的切点通常会使用注解或在Spring配置文件里
采用XML来编写,这两种语法对于Java开发者来说都是相当熟悉的

Spring在运行时通知对象
通过在代理类中包裹切面,Spring在运行期把切面织入到Spring管理
bean中。如图4.3所示,代理类封装了目标类,并拦截被通知方法的
调用,再把调用转发给真正的目标bean。当代理拦截到方法调用时,
在调用目标bean方法之前,会执行切面逻辑。
Spring的切面由包裹了目标对象的代理类实现。
代理类处理方法的调用,执行额外的切面逻辑,并调用目标方法
直到应用需要被代理的bean时,Spring才创建代理对象。如果使用的
ApplicationContext的话,在ApplicationContext
BeanFactory中加载所有bean的时候,Spring才会创建被代理的对
象。因为Spring运行时才创建代理对象,所以我们不需要特殊的编译
器来织入Spring AOP的切面。

 

 

还有Spring只支持方法级别的连接点  因为Spring基于动态代理,所以Spring只支持方法连接点

但是方法拦截可以满足绝大部分的需求。如果需要方法拦截之外的连
接点拦截功能,那么我们可以利用Aspect来补充Spring AOP的功能。

 

Spring借助AspectJ的切点表达式语言来定义Spring切面AspectJ指示器:
arg()  限制连接点匹配参数为指定类型的执行方法
@args()  限制连接点匹配参数由指定注解标注的执行方法
execution()  用于匹配是连接点的执行方法
this()  限制连接点匹配AOP代理的bean引用为指定类型的类
target  限制连接点匹配目标对象为指定类型的类
@target() 限制连接点匹配特定的执行对象,这些对象对应的类要具有指定类型的注解
within() 限制连接点匹配指定的类型
@within() 限制连接点匹配指定注解所标注的类型(当使用Spring AOP时,方法定义在由指定的注解所标注的类里)
@annotation 限定匹配带有指定注解的连接点
Spring中尝试使用AspectJ其他指示器时,将会抛出IllegalArgument-Exception

注意只有execution指示器是实际执行匹配的,而其他的指示器都是用来
限制匹配的。这说明execution指示器是我们在编写切点定义时最
主要使用的指示器。在此基础上,我们使用其他指示器来限制所匹配的切点

所以本例子中我们采用 注解加配置的方式来实现简单的方法调用(也是项目中用的最多的方式)

首先创建一个maven项目

pom.xml中引入依赖:

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

 

    <groupId>com.springAop</groupId>

    <artifactId>springAop</artifactId>

    <version>1.0-SNAPSHOT</version>

 

    <dependencies>

        <dependency>

            <groupId>org.springframework</groupId>

            <artifactId>spring-context</artifactId>

            <version>3.2.8.RELEASE</version>

        </dependency>

        <dependency>

            <groupId>org.springframework</groupId>

            <artifactId>spring-core</artifactId>

            <version>3.2.8.RELEASE</version>

        </dependency>

        <dependency>

            <groupId>org.aspectj</groupId>

            <artifactId>aspectjrt</artifactId>

            <version>1.8.1</version>

        </dependency>

        <dependency>

            <groupId>org.aspectj</groupId>

            <artifactId>aspectjweaver</artifactId>

            <version>1.8.1</version>

        </dependency>

        <dependency>

            <groupId>org.springframework</groupId>

            <artifactId>spring-aop</artifactId>

            <version>3.2.8.RELEASE</version>

        </dependency>

        <dependency>

            <groupId>org.springframework</groupId>

            <artifactId>spring-expression</artifactId>

            <version>3.2.8.RELEASE</version>

        </dependency>

        <dependency>

            <groupId>junit</groupId>

            <artifactId>junit</artifactId>

            <version>4.12</version>

        </dependency>

        <dependency>

            <groupId>org.springframework</groupId>

            <artifactId>spring-test</artifactId>

            <version>3.1.2.RELEASE</version>

        </dependency>

 

 

    </dependencies>

 

</project>

 

首先我们定义一个接口(演出类):

package demo01;

/** * Created by 340092 on 2017/11/13. */public interface Performance {

    /**     * 测试 Before()  after()  After-returning(返回后) After-throwing(抛出后)     */    void perform();

 

     /**      * 测试环绕 Arround(周围)      */     void performAround();

 

     /**      * 测试携带参数的AOP      * @param name      */     void performArgs(String name);

}

定义一个实现类 实现Performance 接口

package demo01;

import org.springframework.stereotype.Component;

/** * Created by 340092 on 2017/11/13. */@Componentpublic class PerformanceImpl  implements Performance{

    public void perform() {

        System.out.println("演出开始!!!");

    }

 

    public void performAround() {

        System.out.println("演出开始!!!(测试环绕通知)");

    }

 

    public void performArgs(String name) {

        System.out.println("演出开始!!!(携带参数)"+name);

    }

 

}

定义一个切面采用@Aspect

package demo01;

 

import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.*;import org.springframework.stereotype.Component;

/** * Created by 340092 on 2017/11/13. */@Component@Aspectpublic class Audience {

 

我们使用execution()指示器选择Performance的perform()方
法。方法表达式以“*”号开始,表明了我们不关心方法返回值的类
型。然后,我们指定了全限定类名和方法名。对于方法参数列表,我
们使用两个点号(..)表明切点要选择任意的perform()方法,无
论该方法的入参是什么。

现在假设我们需要配置的切点仅匹配concert包

 

请注意我们使用了“&&”操作符把execution()和within()指示器
连接在一起形成与(and)关系(切点必须匹配所有的指示器)。类
似地,我们可以使用“||”操作符来标识或(or)关系,而使用“!”操
作符来标识非(not)操作。
因为“&”在XML中有特殊含义,所以在Spring的XML配置里面描述切
点时,我们可以使用and来代替“&&”。同样,or和not可以分别用来
代替“||”和“!”。

 

Spring还引入了一个新的bean()指示器,

 

它允许我们在切点表达式中使用bean的ID来标识bean。bean()
使用bean ID或bean名称作为参数来限制切点只匹配特定的bean。
例如,考虑如下的切点:
在这里,我们希望在执行Performance的perform()方法时应用通
知,但限定bean的ID为woodstock

 

在某些场景下,限定切点为指定的bean或许很有意义,但我们还可以
使用非操作为除了特定ID以外的其他bean应用通知:

 

在此场景下,切面的通知会被编织到所有ID不为woodstock的bean

        @Pointcut("execution(* demo01.Performance.perform(..))")

    public void performance(){

 

    }

    @Before("performance()")

    public void silenceCellPhones(){

        System.out.println("表演之前关闭手机");

    }

    @Before("performance()")

    public void takeSeats(){

        System.out.println("表演之前找到座位");

    }

    @AfterReturning("performance()")

    public void applause(){

        System.out.println("观众离开");

    }

    @AfterThrowing("performance()")

    public void demandRefund(){

        System.out.println("表演失败 要求退钱");

    }

    @After("performance()")

    public void partir(){

        System.out.println("如果精彩观众热烈鼓掌");

    }

 

 

    @Pointcut("execution(* demo01.Performance.performAround(..))")

    public void performAround(){

 

    }

//环绕通知是最为强大的通知类型。它能够让你所编写的逻辑将被通知
//的目标方法完全包装起来。实际上就像在一个通知方法中同时编写前
//置通知和后置通知。。

//可以看到,这个通知所达到的效果与之前的前置通知和后置通知是一
//样的。但是,现在它们位于同一个方法中,不像之前那样分散在四个
//不同的通知方法里面

//关于这个新的通知方法,你首先注意到的可能是它接受
//ProceedingJoinPoint作为参数。这个对象是必须要有的,因为
//你要在通知中通过它来调用被通知的方法。通知方法中可以做任何的
//事情,当要将控制权交给被通知的方法时,它需要调
//用ProceedingJoinPoint的proceed()方法。
//需要注意的是,别忘记调用proceed()方法。如果不调这个方法的
//话,那么你的通知实际上会阻塞对被通知方法的调用。有可能这就是
//你想要的效果,但更多的情况是你希望在某个点上执行被通知的方法。
/有意思的是,你可以不调用proceed()方法,从而阻塞对被通知方
//法的访问,与之类似,你也可以在通知中对它进行多次调用。要这样
//做的一个场景就是实现重试逻辑,也就是在被通知方法失败后,进行重复尝试。

    @Around("performAround()")

    public void around(ProceedingJoinPoint p){

        try {

            System.out.println("表演之前关闭手机(测试环绕通知)");

            System.out.println("表演之前找到座位(测试环绕通知)");

 

            p.proceed();//执行原来的方法

            System.out.println("观众离开(测试环绕通知)");

            System.out.println("如果精彩观众热烈鼓掌(测试环绕通知)");

        } catch (Exception e) {

            System.out.println("表演失败 要求退钱(测试环绕通知)");

        } catch (Throwable throwable) {

            System.out.println("表演失败 要求退钱(测试环绕通知)");

            throwable.printStackTrace();

        }

    }

如果切面所通知的方法确实有参数该怎么办呢

 

参数的名称trackNumber也与切点方法签名中的参数相匹配 这个参数会传递到通知方法中

    @Pointcut("execution(* demo01.Performance.performArgs(String))&&args(name)")

    public void performArgs(String name){

    }

    @Before("performArgs(name)")

    public void after(String name){

        System.out.println("表演之前关闭手机,今天的表演者"+name);

    }

    @After("performArgs(name)")

    public void before(String name){

        System.out.println("表演结束,今天的表演者"+name);

    }

}

需要注意的是,除了注解和没有实际操作的performance()方
法,Audience类依然是一个POJO。我们能够像使用其他的Java类那
样调用它的方法,它的方法也能够独立地进行单元测试,这与其他的
Java类并没有什么区别。Audience只是一个Java类,只不过它通过
注解表明会作为切面使用而已。

像其他的Java类一样,通过@Component注解它可以装配为Spring中的bean

如果你就此止步的话,Audience只会是Spring容器中的一个bean。
即便使用了AspectJ注解,但它并不会被视为切面,这些注解不会解
析,也不会创建将其转换为切面的代理 如果你使用JavaConfig的话,可以在配置类的类级别上通过使
EnableAspectJ-AutoProxy注解启用自动代理功能 比如:

package javaConfig;

import demo01.Audience;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.EnableAspectJAutoProxy;

/** * Created by 340092 on 2017/11/13. * @EnableAspectJAutoProxy 启动aop自动代理 .xml文件中<aop:aspectj-autoproxy/>功能一样 */@Configuration@EnableAspectJAutoProxy@ComponentScan(basePackages = "demo01")public class AopConfig {

 

}

如果是.xml的话

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:aop="http://www.springframework.org/schema/aop"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

 

    <context:component-scan base-package="demo01"/>

    <aop:aspectj-autoproxy/></beans>

不管你是使用JavaConfig还是XML,AspectJ自动代理都会为使
@Aspect注解的bean创建一个代理,这个代理会围绕着所有该切面
的切点所匹配的bean。 我们需要记住的是,Spring的AspectJ自动代理仅仅使用@AspectJ作
为创建切面的指导,切面依然是基于代理的。在本质上,它依然是
Spring基于代理的切面。这一点非常重要,因为这意味着尽管使用的
@AspectJ注解,但我们仍然限于代理方法的调用。如果想利用
AspectJ的所有能力,我们必须在运行时使用AspectJ并且不依赖Spring
来创建基于代理的切面。

 

到目前为止,在我们所使用的切面中,所包装的都是被通知对象的已
有方法。但是,方法包装仅仅是切面所能实现的功能之一。让我们看
一下如何通过编写切面,为被通知的对象引入全新的功能。

一些编程语言,例如Ruby和Groovy,有开放类的理念。它们可以不用
直接修改对象或类的定义就能够为对象或类增加新的方法。不过,
Java并不是动态语言。一旦类编译完成了,我们就很难再为该类添加
新的功能了

如果切面能够为现有的方法增加额外的功能,为什
么不能为一个对象增加新的方法呢?实际上,利用被称为引入的AOP
概念,切面可以为Spring bean添加新方法

 

使用Spring AOP,我们可以为bean引入新的方法。
代理拦截调用并委托给实现该方法的其他对象 我们需要注意的是,当引入接口的方法被调用时,代理会把此调用委
托给实现了新接口的某个其他对象。实际上,一个bean的实现被拆分
到了多个类中

为了验证该主意能行得通,我们为示例中的所有的Performance实
现引入下面的Encoreable接口

package demo01;

/** * Created by 340092 on 2017/11/13. */public interface Encoreable {

    void performEncore();

}

在建立一个切面

package demo01;

import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.DeclareParents;import org.springframework.stereotype.Component;

/** * Created by 340092 on 2017/11/13. */@Aspect@Componentpublic class EncoreableIntroducer {

    @DeclareParents(value = "demo01.Performance+",defaultImpl = DefaultEncoreable.class)

    public static Encoreable encoreable;

}

 

可以看到,EncoreableIntroducer是一个切面。但是,它与我们
之前所创建的切面不同,它并没有提供前置、后置或环绕通知,而是
通过@DeclareParents注解,将Encoreable接口引入
Performance bean中。

@DeclareParents注解由三部分组成:
value属性指定了哪种类型的bean要引入该接口。在本例中,也
就是所有实现Performance的类型。(标记符后面的加号表示
Performance的所有子类型,而不是Performance本
身。)
defaultImpl属性指定了为引入功能提供实现的类。在这里,
我们指定的是DefaultEncoreable提供实现。
@DeclareParents注解所标注的静态属性指明了要引入了接
口。在这里,我们所引入的是Encoreable接口。
和其他的切面一样,我们需要在Spring应用中用@Component
EncoreableIntroducer声明为一个bean

 

DefaultEncoreable默认实现类:

package demo01;

import org.springframework.stereotype.Component;

/** * Created by 340092 on 2017/11/13. */public class DefaultEncoreable implements Encoreable {

    public void performEncore() {

        System.out.println("默认实现Encoreable接口+TestAop");

    }

}

 

这个Encoreable现在就是被PerformanceImpl实现  所以可以通过向下转型获得Encoreable

然后编写测试类:

import demo01.Encoreable;import demo01.Performance;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/** * Created by 340092 on 2017/11/13. */@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = "classpath:spring1.xml")public class TestAop1 {

    @Autowired    demo02.Performance performance;

    @Test    public void sajkdg(){

        performance.perform();

   }

//之前关闭手机
//之前找到座位
//开始!!!+demo02
//精彩观众热烈鼓掌
//离开

    @Test    public void sajkdgas(){

        performance.performAround();

    }

//之前关闭手机(测试环绕通知)
//之前找到座位(测试环绕通知)
//开始!!!(测试环绕通知)+demo02
//离开(测试环绕通知)
//精彩观众热烈鼓掌(测试环绕通知)

    @Test    public void sajkdhj(){

        performance.performArgs("zhanjie");

    }

//之前关闭手机,今天的表演者zhanjie
//开始!!!+demo02zhanjie
//结束,今天的表演者zhanjie

    @Test    public void uysahdbx(){

        //这个Encoreable现在就是被PerformanceImpl实现  所以可以通过向下转型获得Encoreable        demo02.Encoreable e =(demo02.Encoreable) performance;

        e.performEncore();

 

    }

//实现Encoreable接口+TestAop1

}

 

 

还有一种在XML中声明切面但是,如果你需要声明切面,但是又不能为通知类添加注解的时候,那么就必须转向XML配置了

Spring的aop命名空间中,提供了多个元素用来在XML中声明切面  Spring的AOP配置元素能够以非侵入性的方式声明切

 

<aop:advisor> 定义AOP通知器
<aop:after> 定义AOP后置通知(不管被通知的方法是否执行成功)
<aop:after-returning>定义AOP返回通知
<aop:after-throwing>定义AOP异常通知
<aop:around> 定义AOP环绕通知
<aop:aspect> 定义一个切面
<aop:aspectj-autoproxy>启用 @AspectJ 注解驱动的切面
<aop:before> 定义一个AOP前置通知
<aop:config>顶层的AOP配置元素。大多数的 <aop:*> 元素必须包含在 <aop:config> 元素内
<aop:declare-parents>以透明的方式为被通知的对象引入额外的接口
<aop:pointcut> 定义一个切点
我们已经看过了<aop:aspectj-autoproxy>元素,它能够自动代
AspectJ注解的通知类。aop命名空间的其他元素能够让我们直接在
Spring配置中声明切面,而不需要使用注解。还是上面的类我们把aop的注解去掉

配置文件这样写 效果和之前是一样的

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:aop="http://www.springframework.org/schema/aop"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

        <context:component-scan base-package="demo02"/>

        <bean id="audience" class="demo02.Audience"/>

        <aop:config>

            <aop:aspect id="aop" ref="audience">

                    <aop:pointcut id="cut" expression="execution(* demo02.Performance.perform(..))"/>

                    <aop:before method="silenceCellPhones" pointcut-ref="cut"/>

                    <aop:before method="takeSeats" pointcut-ref="cut"/>

                    <aop:after-returning method="applause" pointcut-ref="cut"/>

                    <aop:after method="partir" pointcut-ref="cut"/>

                    <aop:after-throwing method="demandRefund" pointcut-ref="cut"/>

                    <aop:around method="around" pointcut="execution(* demo02.Performance.performAround(..))"/>

            </aop:aspect>

<!--这里使用and关键字而不是“&&”(因为在XML中,“&”符号会被解析为实体的开始-->

           <aop:aspect id="aop1" ref="audience">

                   <aop:pointcut id="cut1" expression="execution(* demo02.Performance.performArgs(String)) and args(name)"/>

                    <aop:before method="before" pointcut-ref="cut1" />

                    <aop:after method="after"  pointcut-ref="cut1"/>

            </aop:aspect>

            <aop:aspect >

            <!--顾名思义,<aop:declare-parents>声明了此切面所通知的bean要在它的对象层次结构中拥有新的父类型。具体到本例中,类型匹配Performance接口(由types-matching属性指定)的那些bean在父类结构中会增加Encoreable接口(由implement-interface属性指定)。最后要解决的问题是Encoreable接口中的方法实现要来自于何处。这里有两种方式标识所引入接口的实现。在本例中,我们使用default-impl属性用全限定类名来显式指定Encoreable的实现。或者,我们还可以使用delegate-ref属性来标识。delegate-ref属性引用了一个Spring bean作为引入的委托。这需要在Spring上下文中存在一个IDencoreableDelegatebean。使用default-impl来直接标识委托和间接使用delegate-ref的区别在于后者是Spring bean,它本身可以被注入、通知或使用其他的Spring配置。-->

                    <aop:declare-parents types-matching="demo02.Performance+"                                         implement-interface="demo02.Encoreable"                                         default-impl="demo02.DefaultEncoreable"/>

            </aop:aspect>

        </aop:config></beans>

 

 

AOP是面向对象编程的一个强大补充。通过AspectJ,我们现在可以把
之前分散在应用各处的行为放入可重用的模块中。我们显示地声明在
何处如何应用该行为。这有效减少了代码冗余,并让我们的类关注自
身的主要功能。
Spring提供了一个AOP框架,让我们把切面插入到方法执行的周围。
现在我们已经学会如何把通知织入前置、后置和环绕方法的调用中,
以及为处理异常增加自定义的行为。
171
关于在Spring应用中如何使用切面,我们可以有多种选择。通过使
@AspectJ注解和简化的配置命名空间,在Spring中装配通知和切
点变得非常简单。
最后,当Spring AOP不能满足需求时,我们必须转向更为强大的
AspectJ。对于这些场景,我们了解了如何使用Spring为AspectJ切面注
入依赖。
此时此刻,我们已经覆盖了Spring框架的基础知识,了解到如何配置
Spring容器以及如何为Spring管理的对象应用切面。正如我们所看到
的,这些核心技术为创建松散耦合的应用奠定了坚实的基础。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值