写在前面

  在之前的文章中有写到,Spring在配置中,会存在大量的切面配置。然而在很多情况下,SpringAOP 所提供的切面类真的不是很够用,比如想拦截制定的注解方法,我们就必须扩展DefalutPointAdviso类,自定义一个切面类,然后在Spring配置文件中进行切面的配置。

  (Spring+AspectJ) Spring集成了AspectJ,同时保留了以上提到的切面与代理配置方式(为了兼容老的项目)。

  使用AspectJ需要引入对于的jar文件

            <dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.6</version>
</dependency>

Spring + AspectJ(基于注解:通过AspectJ execution 表达式拦截方法)

  下面以一个最简单的例子来实现之前提到的环绕同一种。先定义一个Aspect切面类:

@Aspect
@Component
public class GreetingAspect {
@Around("execution(* aop.demo.GreetingImpl.*())")
public Object arount(ProceedingJoinPoint pjp) throws Throwable{
before();
Object obj = pjp.proceed();
after();
return obj;
}
private void after() {
System.out.println("before advice");
}
private void before() {
System.out.println("after advice");
}
}

  注意:类上面标志的Aspect注解表明该类是一个Aspect(在Spring 体系这个其实就是一个Advisor)。该类无须实现任何接口,只需要定义一个方法(名称无所谓),在方法上标注Arount注解,在注解中共使用AspectJ 切点表达式。方法中的参数包括一个ProceedingJoinPoint对象,它在AOP 体系中成为Joinpoint(连接点),可以通过该对象获取方法的任何信息。

  分析一个这个切点表达式 execution(* aop.demo.GreetingImpl.*())

    execution() 表示拦截方法;

    第一个* 表示方法的返回值是任意类型;

    第二个* 表示匹配该类中的所有方法;

    (..)表示方法的参数是任意类型的。

  在Spring 中 XML 的配置文件如下(配置就是这么简单):

    <!-- 自动扫描注解 -->
<context:component-scan base-package="com.xxx.*" />
<!-- 开启切面编程(通过配置织入@Aspectj切面 ) -->
<aop:aspectj-autoproxy proxy-target-class="true"/>

Spring + AspectJ(基于注解:通过AspectJ @annotation 表达式拦截方法)

  为了拦截指定的注解的方法,我们首先需要来定义一个注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodLog {
}

将之前的Aspect类的切点表达式稍作一下改动:

@Aspect
@Component
public class GreetingAspect {
@Around("@annotation(aop.demo.MethodLog)")
public Object arount(ProceedingJoinPoint pjp) throws Throwable{
before();
Object obj = pjp.proceed();
after();
return obj;
}
private void after() {
System.out.println("before advice");
}
private void before() {
System.out.println("after advice");
}
}

  这次使用了@annotation() 表达式,需要要在括号内定义需要拦截的注解名称即可。直接将MethodLog注解定义在需要拦截的方法上,就是这么简单。

@Component
public class GreetingImpl {
@MehtodLog
public void sayHello(){
System.out.println("hello java");
}
}

  这里只有一个方法,如果有多个方法,我们只想拦截其中的某一个时,这种解决方法会很好。

Spring + AspectJ(引入增强)

  为了实现基于AspectJ 的引入增强,我们同样需要定义一个Aspect 类:

@Aspect
@Component
public class GreetingAspect {
@DeclareParents(value="aop.demo.GreetingImpl", defaultImpl = ApologyImpl.class)
private Apology Apology;
}

  在Aspect 类中定义一个需要引入增强的接口,它就是运行时需要动态实现的接口。在这个接口上标注了DeclareParents注解,该注解有两个属性:

    value ---目标类;

    defaultImpl ---引入接口的默认实现类。

  我们需要对引入的接口提供一个默认的实现类就可以完成引入的增强:

public class ApologyImpl implements Apology{
@Override
public void saySorry() {
System.out.println("我是增强类, 我说sorry");
}
}

  以上这个实现hi在运行时自动增强到GreetingImpl类中,也就是说,无须修改GreetImpl类的代码,让它去实现Apology 接口,我们单独为该接口提供一个实现类(ApologyImpl)来做GreetingImpl 想做的事情。

 测试代码:

        ApplicationContext context = new FileSystemXmlApplicationContext("beans-config.xml");
Greeting proxy = (Greeting) context.getBean("greetimpl");
proxy.sayHello();
// 看来好像 Apology 物件动态增加了职责
((Apology) proxy).saySorry();

运行结果:

hello java
我是增强类, 我说sorry

Aspect其他注解介绍

  Before ----- 前置增强;

  After ----- 后置增强;

  Around ----- 环绕增强;

  AfterThrowing ----- 抛出增强;

  DeclareParents ----- 引入增强。

Spring + AspectJ(基于配置)

  使用AspectJ 的增强 比原来 的Spring AOP 增强很方便,这算是一个巨大的突破。但是任然有用户不能尝试这些特性,因为他们还在使用低于JDK 1.5 (没有注解)。spring 提供配置解决了这个问题。

   <bean id="greetingImpl" class="aop.demo.GreetingImpl" />
<bean id="greetingAspect" class="aop.demo.GreetingAspect" />
<aop:config>
<aop:aspect ref="greetingAspect">
<aop:around method="around" pointcut="execution(* aop.demo.GreetingImpl.*(..))"/>
</aop:aspect>
</aop:config>

  使用<aop:config> 元素来进行AOP 配置,在其子元素中配置切面,包括增强类型,目标方法,切点等信息。

总结

  各类增强类型对于的解决方法:

  增强类型            基于AOP                基于AOP注解          基于<aop:cofnig> 配置

  BefooreAdvice(前置增强)    MethodBeforeAdvice          @Before           <aop:before>

  AfterAdvice(后置增强)      AfterReturningAdIve           @After            <aop:after>

  AroundAdvice(环绕增强)    MethodInterceptor            @Around             <aop:around>

  ThrowsAdvice(异常增强)    ThrowsAdvice             @AfterThrowing        <aop:after-throwing>

  IntroductionAdvice(引入增强)  DelegatingIntroductionInteceptor       @DeclareParents        <aop:declare-parents>

Spring AOP 的整体架构

spring---aop(10)---Spring AOP中AspectJ的更多相关文章

  1. 04 Spring:01.Spring框架简介&&02.程序间耦合&&03.Spring的 IOC 和 DI&&08.面向切面编程 AOP&&10.Spring中事务控制

    spring共四天 第一天:spring框架的概述以及spring中基于XML的IOC配置 第二天:spring中基于注解的IOC和ioc的案例 第三天:spring中的aop和基于XML以及注解的A ...

  2. 10 Spring框架 AOP (三) Spring对AspectJ的整合

    上两节我们讲了Spring对AOP的实现,但是在我们的开发中我们不太使用Spring自身的对AOP的实现,而是使用AspectJ,AspectJ是一个面向切面的框架,它扩展了Java语言.Aspect ...

  3. Spring 源码学习笔记10——Spring AOP

    Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...

  4. 【spring 5】AOP:spring中对于AOP的的实现

    在前两篇博客中,介绍了AOP实现的基础:静态代理和动态代理,这篇博客介绍spring中AOP的实现. 一.采用Annotation方式 首先引入jar包:aspectjrt.jar && ...

  5. SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP

    AOP(Aspect Oriented Programming),是面向切面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP之所以能得到广泛应用,主要是因为它将应用系统拆分分了2个部分 ...

  6. spring aop方式配置事务中的三个概念 pointcut advice advisor

    AOP的3个关键概念 因为AOP的概念难于理解,所以在前面首先对Java动态代理机制进行了一下讲解,从而使读者能够循序渐进地来理解AOP的思想. 学习AOP,关键在于理解AOP的思想,能够使用AOP. ...

  7. 10.Spring——框架的AOP

    1.Spring 框架的 AOP 2.Spring 中基于 AOP 的 XML架构 3.Spring 中基于 AOP 的 @AspectJ 1.Spring 框架的 AOP Spring 框架的一个关 ...

  8. AOP 与 Spring中AOP使用(上)

    AOP简介 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程, 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP是OOP的延续 ...

  9. JavaWeb_(Spring框架)认识Spring中的aop

    1.aop思想介绍(面向切面编程):将纵向重复代码,横向抽取解决,简称:横切 2.Spring中的aop:无需我们自己写动态代理的代码,spring可以将容器中管理对象生成动态代理对象,前提是我们对他 ...

随机推荐

  1. Django BoundField

    一.BoundField from django.forms.boundfield import BoundField BoundField是一个将字段添加数据的一个类,给对应的form字段封装上数据 ...

  2. 理解 Linux 的硬链接与软链接(待研究)

    从 inode 了解 Linux 文件系统 硬链接与软链接是 Linux 文件系统中的一个重要概念,其涉及文件系统中的索引节点 (index node 又称 inode),而索引节点对象是 Linux ...

  3. 【Android开发】之MediaPlayer的错误分析

    最近在做媒体播放器,使用了Android自带的MediaPlayer,经常性会碰到MediaPlayer报错的情况,找过网上的,感觉总结的不是很好或者比较散.下面,我来总结一下使用MediaPlaye ...

  4. 浅谈js设计模式之策略模式

    策略模式有着广泛的应用.本节我们就以年终奖的计算为例进行介绍. 很多公司的年终奖是根据员工的工资基数和年底绩效情况来发放的.例如,绩效为 S的人年终奖有 4倍工资,绩效为 A的人年终奖有 3倍工资,而 ...

  5. git忽略特殊文件或文件夹

    1.在项目目录中添加“.gitignore”文件,项目目录就是你存放git工程的目录就是有“.git”目录的目录 vi .gitignore 2.在文件中添加如下内容,其中“/runtime/”是忽略 ...

  6. java基础67 JavaScript通过关系找节点、添加附件(网页知识)

    1.通过关系找节点(父子关系,兄弟关系) 1.1.常用方法 parentNode:获取当前元素的父节点.    childNodes:获取当前元素的所有下一级子元素    firstChild:获取当 ...

  7. [android] The_connection_to_adb_is_down__and_a_severe_error_has_occured解决方案

    初学安卓,这是我碰到的第一个问题,从网上找了些解决方法,同时也把问题解决了. 方案一 1.先把eclipse关闭. 2.在管理器转到你的android SDK 的platform-tools下, 如图 ...

  8. php和mysql两种不同方式的分割字符串和类型转换

    一.sql语句1.分割字符串方法:substring_index(字符串,'分隔符',正数从左数起几位/负数从右数起几位); 例如:subtring_index('aa_bb_cc_dd','_',1 ...

  9. SQL SERVER2008 存储过程、表、视图、函数的权限

    EXEC sp_addrolemember N'db_owner', N'db'----将db 设置为 db_owner 角色中的一员 EXEC sp_droprolemember N'db_owne ...

  10. MFC+WinPcap编写一个嗅探器之四(获取模块)

    这一节主要介绍如何获取设备列表,比较简单 获取设备列表主要是在CAdpDlg中完成,也就是对应之前创建的选择适配器模块,如图: 当打开选择适配器对话框后,在列表视图控件中显示当前主机所有适配器及适配器 ...