一、aop是什么

1.AOP面向方面编程基于IoC,是对OOP的有益补充;

2.AOP利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了 多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的 逻辑或责任封装起来,比如日志记录,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

3.AOP代表的是一个横向的关 系,将“对象”比作一个空心的圆柱体,其中封装的是对象的属性和行为;则面向方面编程的方法,就是将这个圆柱体以切面形式剖开,选择性的提供业务逻辑。而 剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹,但完成了效果。

4.实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。

二、aop的原理

1.采用动态代理,对被代理对象和特定处理进行修饰和封装,得到代理对象,从使得被代理对象中不需切入任何的代码

2.采用静态织入,如AspectJ,使用其特定的语法创建切面,在编译期间将切面织入代码中。

三、aop的基本概念

切面(ASPECT):横切关注点被模块化的特殊对象。即,它是一个类。

通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。

目标(Target):被通知对象。

代理(Proxy):向目标对象应用通知之后创建的对象。

切入点(PointCut):切面通知执行的“地点”的定义。

连接点(JointPoint):与切入点匹配的执行点。

四、aspectJ的织入方式及其原理概要

ApectJ采用的就是静态织入的方式。ApectJ主要采用的是编译期织入,在这个期间使用AspectJ的acj编译器(类似javac)把aspect类编译成class字节码后,在java目标类编译时织入,即先编译aspect类再编译目标类。

五、spring aop的实现

ApplicationContext.xml 加入

<aop:aspectj-autoproxy/>

创建切面处理类

@Aspect
@Component
public class AspectHandler { @Pointcut("execution(* com.marving.service.BaseServ+.*(..))")
private void doMethod() {
} /**
* This is the method which I would like to execute before a selected method
* execution.
*/
@Before("doMethod()")
public void beforeAdvice() {
System.out.println("before method invoked.");
} /**
* This is the method which I would like to execute after a selected method
* execution.
*/
@After("doMethod()")
public void afterAdvice() {
System.out.println("after method invoked.");
} // 配置controller环绕通知,使用在方法aspect()上注册的切入点
@Around("doMethod()")
public Object around(ProceedingJoinPoint pjp) throws Throwable{
Object result = null;
String methodName = pjp.getSignature().getName();
try {
System.out.println("The method [" + methodName + "] begins with " + Arrays.asList(pjp.getArgs()));
result = pjp.proceed();
} catch (Throwable e) {
System.out.println("The method [" + methodName + "] occurs expection : " + e);
throw new RuntimeException(e);
}
System.out.println("The method [" + methodName + "] ends");
return result;
}
}

使用@Pointcut注解进行定义,应用到通知函数afterDemo()时直接传递切点表达式的函数名称myPointcut()即可,比较简单,下面接着介绍切点指示符。

1.切入点指示符

类型签名表达式

within(<type name>)
//匹配com.mobanker.dao包及其子包中所有类中的所有方法
@Pointcut("within(com.mobanker.dao..*)")
// 匹配UserDaoImpl类中所有方法
@Pointcut("within(com.mobanker.dao.UserDaoImpl)")
// 匹配UserDaoImpl类及其子类中所有方法
@Pointcut("within(com.mobanker.dao.UserDaoImpl+)")
// 匹配所有实现UserDao接口的类的所有方法
@Pointcut("within(com.mobanker.dao.UserDao+)")

方法签名表达式

//scope :方法作用域,如public,private,protect
// returnt-type:方法返回值类型
// fully-qualified-class-name:方法所在类的完全限定名称
// parameters 方法参数
execution(<scope><return-type><fully-qualified-class-name>.*(parameters))
//匹配UserDaoImpl类中的所有方法
@Pointcut("execution(* com.mobanker.dao.UserDaoImpl.*(..))")
//匹配UserDaoImpl类中的所有公共的方法
@Pointcut("execution(public * com.mobanker.dao.UserDaoImpl.*(..))")
// 匹配UserDaoImpl类中的所有公共方法并且返回值为int类型
@Pointcut("execution(public int com.mobanker.dao.UserDaoImpl.*(..))")
// 匹配UserDaoImpl类中第一个参数为int类型的所有公共的方法
@Pointcut("execution(public * com.mobanker.dao.UserDaoImpl.*(int , ..))")

其它指示符

bean:Spring AOP扩展的,AspectJ没有对于指示符,用于匹配特定名称的Bean对象的执行方法;

//匹配名称中带有后缀Service的Bean。
@Pointcut("bean(*Service)")
private void myPointcut1(){}

this :用于匹配当前AOP代理对象类型的执行方法;请注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配

//匹配了任意实现了UserDao接口的代理对象的方法进行过滤
@Pointcut("this(com.mobanker.spring.springAop.dao.UserDao)")
private void myPointcut2(){}

target :用于匹配当前目标对象类型的执行方法;

//匹配了任意实现了UserDao接口的目标对象的方法进行过滤
@Pointcut("target(com.mobanker.spring.springAop.dao.UserDao)")
private void myPointcut3(){}

@within:用于匹配所以持有指定注解类型内的方法;请注意与within是有区别的, within是用于匹配指定类型内的方法执行;

//匹配使用了MarkerAnnotation注解的类(注意是类)
@Pointcut("@within(com.mobanker.spring.annotation.MarkerAnnotation)")
private void myPointcut4(){}

@annotation(com.mobanker.spring.MarkerMethodAnnotation) : 根据所应用的注解进行方法过滤

//匹配使用了MarkerAnnotation注解的方法(注意是方法)
@Pointcut("@annotation(com.mobanker.spring.annotation.MarkerAnnotation)")
private void myPointcut5(){}

2.5种通知函数

前置通知@Before

  前置通知通过@Before注解进行标注,并可直接传入切点表达式的值,该通知在目标函数执行前执行,注意JoinPoint,是Spring提供的静态变量,通过joinPoint 参数,可以获取目标对象的信息,如类名称,方法参数,方法名称等,,该参数是可选的。

/**
* 前置通知
* @param joinPoint 该参数可以获取目标对象的信息,如类名称,方法参数,方法名称等
*/
@Before("execution(* com.mobanker.spring.springAop.dao.UserDao.addUser(..))")
public void before(JoinPoint joinPoint){
System.out.println("我是前置通知");
}

后置通知@AfterReturning
  通过@AfterReturning注解进行标注,该函数在目标函数执行完成后执行,并可以获取到目标函数最终的返回值returnVal,当目标函数没有返回值时,returnVal将返回null,必须通过returning = “returnVal”注明参数的名称而且必须与通知函数的参数名称相同。请注意,在任何通知中这些参数都是可选的,需要使用时直接填写即可,不需要使用时,可以完成不用声明出来。如下

/**
* 后置通知
* returnVal,切点方法执行后的返回值
*/
@AfterReturning(value="execution(* com.mobanker.spring.springAop.dao.UserDao.*User(..))",returning = "returnVal")
public void AfterReturning(JoinPoint joinPoint,Object returnVal){
System.out.println("我是后置通知...returnVal+"+returnVal);
}

异常通知 @AfterThrowing

  该通知只有在异常时才会被触发,并由throwing来声明一个接收异常信息的变量,同样异常通知也用于Joinpoint参数,需要时加上即可,如下:

/**
* 抛出通知
* @param e 抛出异常的信息
*/
@AfterThrowing(value="execution(* com.mobanker.spring.springAop.dao.UserDao.addUser(..))",throwing = "e")
public void afterThrowable(Throwable e){
System.out.println("出现异常:msg="+e.getMessage());
}

最终通知 @After

  该通知有点类似于finally代码块,只要应用了无论什么情况下都会执行。

/**
* 无论什么情况下都会执行的方法
* joinPoint 参数
*/
@After("execution(* com.mobanker.spring.springAop.dao.UserDao.*User(..))")
public void after(JoinPoint joinPoint) {
System.out.println("最终通知....");
}

环绕通知@Around

  环绕通知既可以在目标方法前执行也可在目标方法之后执行,更重要的是环绕通知可以控制目标方法是否指向执行,但即使如此,我们应该尽量以最简单的方式满足需求,在仅需在目标方法前执行时,应该采用前置通知而非环绕通知。案例代码如下第一个参数必须是ProceedingJoinPoint,通过该对象的proceed()方法来执行目标函数,proceed()的返回值就是环绕通知的返回值。同样的,ProceedingJoinPoint对象也是可以获取目标对象的信息,如类名称,方法参数,方法名称等等。

@Around("execution(* com.mobanker.spring.springAop.dao.UserDao.*User(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("我是环绕通知前....");
//执行目标函数
Object obj= (Object) joinPoint.proceed();
System.out.println("我是环绕通知后....");
return obj;
}

图片和内容:https://blog.csdn.net/javazejian/article/details/56267036

spring aop原理和实现的更多相关文章

  1. 面试问烂的 Spring AOP 原理、SpringMVC 过程(求求你别问了)

    Spring AOP ,SpringMVC ,这两个应该是国内面试必问题,网上有很多答案,其实背背就可以.但今天笔者带大家一起深入浅出源码,看看他的原理.以期让印象更加深刻,面试的时候游刃有余. Sp ...

  2. spring ioc 原理 spring aop原理

    大家一直都说spring的IOC如何如何的强大,其实我倒觉得不是IOC如何的强大,说白了IOC其实也非常的简单.我们先从IOC说起,这个概念其实是从我们平常new一个对象的对立面来说的,我们平常使用对 ...

  3. spring aop原理分析

    持续更新... aop跟java代理模式有关. java.lang.reflect.Proxy java.lang.reflect.InvocationHandler 工厂模式用到java反射. ao ...

  4. Spring AOP原理(续)

    十二.AOP 1. 说出Spring的通知类型有哪些? spring共提供了五种类型的通知: 通知类型 接口 描述 Around 环绕通知 org.aopalliance.intercept.Meth ...

  5. spring aop 原理学习

    @EnableAspectJAutoProxy: @Import(AspectJAutoProxyRegistrar.class) 实际是创建了一个以org.springframework.aop.c ...

  6. Spring Boot -- Spring AOP原理及简单实现

    一.AOP基本概念 什么是AOP,AOP英语全名就是Aspect oriented programming,字面意思就是面向切面编程.面向切面的编程是对面向对象编程的补充,面向对象的编程核心模块是类, ...

  7. 【spring 注解驱动开发】Spring AOP原理

    尚学堂spring 注解驱动开发学习笔记之 - AOP原理 AOP原理: 1.AOP原理-AOP功能实现 2.AOP原理-@EnableAspectJAutoProxy 3.AOP原理-Annotat ...

  8. Spring AOP 原理的理解

    >AOP基本概念 1)通知(Advice):织入到目标类连接点上的一段程序代码.通知分为五种类型: - Before:在方法被调用之前调用 - After:在方法完成后调用通知,无论方法是否执行 ...

  9. Spring AOP原理及拦截器

    原理 AOP(Aspect Oriented Programming),也就是面向方面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP将应用系统分为两部分,核心业务逻辑(Core bu ...

随机推荐

  1. sqlalchemy怎么order_by降序/升序并取第一条数据

    原文链接:https://blog.csdn.net/mark4541437/article/details/103755721 sqlalchemy怎么order_by降序/升序并取第一条数据 fr ...

  2. 焦大:逛网seo案例浅析

    http://www.wocaoseo.com/thread-93-1-1.html 逛,发现喜欢.这或许是很多人上网的喜欢方式,我隐约记得白鸦在一次采访上说到现在人的购物方式,在淘宝上人们决定买一件 ...

  3. Mac 系统安装robot framework

    1.安装Python3 版本 2.安装robotframework:pip3 install robotframework 3.安装Pypubsub:pip3 install Pypubsub 4.安 ...

  4. Asterisk-WebRTC客户端的部署

    很久没有写博客了.最近完成asterisk 和  jssip的库集成,浏览器支持chrome/firefox.在集成的过程中遇到了一些问题,在这儿分享出来,免得大家走弯路. 在网上看一些帖子,环境都是 ...

  5. 2. Bean Validation声明式校验方法的参数、返回值

    你必须非常努力,才能干起来毫不费力.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习.关注公众 ...

  6. 关于bat批处理的一些操作,如启动jar 关闭进程等

    先说一下学习这个的前提: 公司要写个生成uid的工具,整完了之后就又整批处理工具,出于此目的,也是为了丰富自己的知识,就学习了一下,下面是相关的批处理脚本 我花了半天的时间找了相关的bat批处理,但是 ...

  7. 关于babel你需要知道的事情

    babel js转码器 ES6 ==> ES5 配置 .babelrc

  8. cordova 环境配制和创建插件

    环境配制 英文网站:http://cordova.apache.org/ 中文网站:http://cordova.axuer.com/ 安装Cordova Cordova的命令行运行在Node.js ...

  9. windows远程连接老是出问题?如何使用Radmin进行云服务器的远程连接与文件传输?

    (windows远程连接老是出错怎么办?云服务器远程连接一直有问题怎么办?如何用对多台windows电脑远程连接怎么办? 最近发现win的mstsc不好用,偶然想起Radmin这款老牌软件,利用Rad ...

  10. Codeforces Round #560 (Div. 3)A-E

    A. Remainder output standard output You are given a huge decimal number consisting of nn digits. It ...