写在前面

  在之前的文章中有写到,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. python去除html空格

    如下面的 <td> 柳暗花溟</td> html里面的空格&nbsp,想直接用strip()函数去除是不可能的,必须显式的去掉\xa0 例如以上的就可以这样的方式去除空 ...

  2. AdvStringGrid 垂直居中 、水平居中

    官网faq,解答: 结果:

  3. MICROSOFT SQLSERVER 总结

    --语 句 功 能--数据操作Select --从数据库表中检索数据行和列Insert --向数据库表添加新数据行Delete --从数据库表中删除数据行Update --更新数据库表中的数据--数据 ...

  4. MySQL权限问题

    1.修改MySQL用户密码 .先来看一个PASSWORD()函数,MYSQL使用MD5加密 SELECT PASSWORD(‘root’); .使用mysql数据库,查看用户表 USE mysql; ...

  5. JS实现点击图片,在浏览器中查看。

    工作中遇到要实现点击图片查看的功能,从网上找了一段js代码,可以用. <img src="/pic/${pictureCertificate}" alt="凭证&q ...

  6. 洛谷 P1992 不想兜圈的老爷爷 题解

    洛谷 P1992 不想兜圈的老爷爷 题解 题目描述 一位年过古稀的老爷爷在乡间行走 而他不想兜圈子 因为那会使他昏沉 偶然路过小A发扬助人为乐优良传统 带上地图 想知道路况是否一定使他清醒 usqwe ...

  7. CCF CSP 201709-3 JSON查询

    CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201709-3 JSON查询 问题描述 JSON (JavaScript Object Not ...

  8. bzoj 1826

    思路:贪心取最后出现的. #include<bits/stdc++.h> #define LL long long #define fi first #define se second # ...

  9. Buffer对象的总结

    1.首先记录下php关于字符串长度的统计 <?php echo '<br>'; echo '<br>'; 2.Buffer对象为16进制的两位数,即FF 0-225: v ...

  10. Python 爬虫个人笔记【目录】

    个人笔记,仅供参考 目录 Python爬虫笔记(一) Python 爬虫笔记(二) Python 爬虫笔记(三) Scrapy 笔记(一) Scrapy 笔记(二) Scrapy 笔记(三) Pyth ...