写在前面

  在之前的文章中有写到,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. 七、springcloud之配置中心Config(二)之高可用集群

    方案一:传统作法(不推荐) 服务端负载均衡 将所有的Config Server都指向同一个Git仓库,这样所有的配置内容就通过统一的共享文件系统来维护,而客户端在指定Config Server位置时, ...

  2. docker stack 部署容器监控方案(cAdvisor、Prometheus、Grafana)

    =============================================== 2018/7/8_第1次修改                       ccb_warlock === ...

  3. 使用Scrapy命令行工具【导出JSON文件】时编码设置

    Windows 10家庭中文版,Python 3.6.4,virtualenv 16.0.0,Scrapy 1.5.0, 使用scrapy命令行工具建立了爬虫项目(startproject),并使用s ...

  4. html-示例代码

    <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/html" xml ...

  5. SQLAlchemy-对象关系教程ORM-一对多(外键),一对一,多对多

    一:一对多 表示一对多的关系时,在子表类中通过 foreign key (外键)引用父表类,然后,在父表类中通过 relationship() 方法来引用子表的类. 在一对多的关系中建立双向的关系,这 ...

  6. pyquery学习笔记

    很早就听说了pyquery的强大.写了个简单的测试程序实验下. 思路是找个动态网页,先用PhantomJS加载,然后用PYQUERY解析. 1.随便找了个带表格的股票网页,里面有大量的股票数据,测试的 ...

  7. Python_oldboy_自动化运维之路(八)

    本节内容: 列表生成式,迭代器,生成器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器,生成器 1.列表生成式 #[列表生成] #1.列 ...

  8. 应用服务器中对JDK的epoll空转bug的处理

    原文链接:应用服务器中对JDK的epoll空转bug的处理 前面讲到了epoll的一些机制,与select和poll等传统古老的IO多路复用机制的一些区别,这些区别实质可以总结为一句话, 就是epol ...

  9. 消息 8101,级别 16,状态 1,第 1 行仅当使用了列列表并且 IDENTITY_INSERT 为 ON 时,才能为表'CUSTOMER_TBL'中的标识列指定显式值。

    像这样的问题怎么解决呢? 问题分析: 意思是你的主键是自动编号类型的,所以不能向该列插入数据. 解决办法: 执行 语句 :SET IDENTITY_INSERT CUSTOMER_TBL ON 然后在 ...

  10. LAMP:用yum安装

    LAMP:用yum安装 Table of Contents 1 什么是LAMP 1.1 L 1.2 A 1.3 M 1.4 P 2 什么是yum 3 如何使用yum 3.1 基本的yum命令 3.1. ...