动态代理

代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务

动态代理好比如影星和经纪人,实际演戏的是影星,经纪人为影星处理好拍戏前后的事情.实际演戏的是影星.电影公司找影星拍戏前需要先找到经纪人,但最终拍戏还是得找影星执行这个动作.

 public interface Dinner {//吃晚饭的方法public void haveDinner();
}
//委托类
public class MyDinner implements Dinner{@Overridepublic void haveDinner() {System.out.println("妈妈做的晚饭真好吃....");}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//代理类
public class MyDinnerProxy implements InvocationHandler {private Object originalObject; //被代理的原始对象//绑定被代理对象,返回一个代理对象public Object getProxy(Object obj){this.originalObject = obj;//返回一个代理对象return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);} @Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {Object result = null;System.out.println("吃饭之前洗手保持个人卫生...");result = method.invoke(this.originalObject, args);System.out.println("吃饭之后洗碗保持厨房卫生....");return result;}
}
//测试类
public class MyDinnerProxyDemo {public static void main(String[] args) {Dinner din = new MyDinner();//不是使用代理对象的效果//din.haveDinner();MyDinnerProxy proxy = new MyDinnerProxy();//返回了一个代理对象din = (Dinner)proxy.getProxy(din);//执行代理对象的方法din.haveDinner();}
}

AOP简介

AOP(Aspect-Oriented Programming, 面向切面编程): 是一种新的方法论, 是对传统 OOP(Object-Oriented Programming, 面向对象编程) 的补充.

AOP 的主要编程对象是切面(aspect), 而切面模块化横切关注点.

在应用 AOP 编程时, 仍然需要定义公共功能, 但可以明确的定义这个功能在哪里, 以什么方式应用, 并且不必修改受影响的类. 这样一来横切关注点就被模块化到特殊的对象(切面)里.

AOP 的好处:

–每个事物逻辑位于一个位置, 代码不分散, 便于维护和升级

–业务模块更简洁, 只包含核心业务代码.

切面(Aspect):  横切关注点(跨越应用程序多个模块的功能)被模块化的特殊对象

通知(Advice):  切面必须要完成的工作

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

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

连接点(Joinpoint):程序执行的某个特定位置:如类某个方法调用前、调用后、方法抛出异常后等。连接点由两个信息确定:方法表示的程序执行点;相对点表示的方位。例如 ArithmethicCalculator#add() 方法执行前的连接点,执行点为 ArithmethicCalculator#add(); 方位为该方法执行前的位置

切点(pointcut):每个类都拥有多个连接点:例如 ArithmethicCalculator的所有方法实际上都是连接点,即连接点是程序类中客观存在的事务。AOP 通过切点定位到特定的连接点。类比:连接点相当于数据库中的记录,切点相当于查询条件。切点和连接点不是一对一的关系,一个切点匹配多个连接点,切点通过 org.springframework.aop.Pointcut接口进行描述,它使用类和方法作为连接点的查询条件。  

切面就是一个带有 @Aspect 注解的 Java 类.

切面需要在IOC容器中,@Component

通知是标注有某种注解的简单的 Java 方法.

AspectJ支持 5 种类型的通知注解:

–@Before: 前置通知, 在方法执行之前执行

–@After: 后置通知, 在方法执行之后执行

–@AfterRunning: 返回通知, 在方法返回结果之后执行

–@AfterThrowing: 异常通知, 在方法抛出异常之后

–@Around: 环绕通知, 围绕着方法执行

可以用@Order(1)指定不同切面的优先级(也就是执行顺序),数字越小优先级越高

在 AspectJ切面中, 可以通过 @Pointcut注解将一个切入点声明成简单的方法. 切入点的方法体通常是空的, 因为将切入点定义与应用程序逻辑混在一起是不合理的

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
/*** AOP 的 helloWorld* 1. 加入 jar 包* com.springsource.net.sf.cglib-2.2.0.jar* com.springsource.org.aopalliance-1.0.0.jar* com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar* spring-aspects-4.0.0.RELEASE.jar* * 2. 在 Spring 的配置文件中加入 aop 的命名空间。 * * 3. 基于注解的方式来使用 AOP* 3.1 在配置文件中配置自动扫描的包: <context:component-scan base-package="com.atguigu.spring.aop"></context:component-scan>* 3.2 加入使 AspjectJ 注解起作用的配置: <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 使@Before和@After起作用* 为匹配的类自动生成动态代理对象. * * 4. 编写切面类: * 4.1 一个一般的 Java 类* 4.2 在其中添加要额外实现的功能. ** 5. 配置切面* 5.1 切面必须是 IOC 中的 bean: 添加 @Component 注解* 5.2 声明是一个切面: 添加 @Aspect* 5.3 配置切面优先级@Order(1)* 5.3.1 给方法配置通知注解.
前置通知: @Before("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(int, int))")* 6. 在通知中访问连接细节: 可以在通知方法中添加 JoinPoint 类型的参数, 从中可以访问到目标方法的签名和方法的参数. * */
//通过添加 @Aspect 注解声明一个 bean 是一个切面!
@Order(2)
@Aspect
@Component
public class LoggingAspect {
/*** 定义一个方法, 用于声明切入点表达式. 一般地, 该方法中再不需要添入其他的代码. * 使用 @Pointcut 来声明切入点表达式. * 后面的其他通知直接使用方法名来引用当前的切入点表达式. */@Pointcut("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(..))")public void declareJointPointExpression(){}//声明是一个前置通知,在目标方法之前执行@Before("declareJointPointExpression()")public void beforeMethod(JoinPoint joinPoint){String methodName = joinPoint.getSignature().getName();Object [] args = joinPoint.getArgs();System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));}
//声明是一个后置通知,在目标方法执行后(发生异常后)执行,还不能访问目标方法的执行结果@After("execution(* com.atguigu.spring.aop.*.*(..))")public void afterMethod(JoinPoint joinPoint){String methodName = joinPoint.getSignature().getName();System.out.println("The method " + methodName + " ends");}/*** 在方法法正常结束受执行的代码* 返回通知是可以访问到方法的返回值的!*/@AfterReturning(value="declareJointPointExpression()",returning="result")public void afterReturning(JoinPoint joinPoint, Object result){String methodName = joinPoint.getSignature().getName();System.out.println("The method " + methodName + " ends with " + result);}/*** 在目标方法出现异常时会执行的代码.* 可以访问到异常对象; 且可以指定在出现特定异常时在执行通知代码*/@AfterThrowing(value="declareJointPointExpression()",throwing="e")public void afterThrowing(JoinPoint joinPoint, Exception e){String methodName = joinPoint.getSignature().getName();System.out.println("The method " + methodName + " occurs excetion:" + e);}/*** 环绕通知需要携带 ProceedingJoinPoint 类型的参数. * 环绕通知类似于动态代理的全过程: ProceedingJoinPoint 类型的参数可以决定是否执行目标方法.* 且环绕通知必须有返回值, 返回值即为目标方法的返回值*//*@Around("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(..))")public Object aroundMethod(ProceedingJoinPoint pjd){Object result = null;String methodName = pjd.getSignature().getName();try {//前置通知System.out.println("The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs()));//执行目标方法result = pjd.proceed();//返回通知System.out.println("The method " + methodName + " ends with " + result);} catch (Throwable e) {//异常通知System.out.println("The method " + methodName + " occurs exception:" + e);throw new RuntimeException(e);}//后置通知System.out.println("The method " + methodName + " ends");return result;}
}
//另一个切面
package com.atguigu.spring.aop;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Order(1)
@Aspect
@Component
public class VlidationAspect {
//重用另一个包的一个类里的切入点表达式@Before("com.atguigu.spring.aop.LoggingAspect.declareJointPointExpression()")public void validateArgs(JoinPoint joinPoint){System.out.println("-->validate:" + Arrays.asList(joinPoint.getArgs()));}}

转载于:https://blog.51cto.com/s5650326/1717136

Spring学习之AOP(面向切面编程)相关推荐

  1. python aop编程_学习笔记: AOP面向切面编程和C#多种实现

    AOP:面向切面编程   编程思想 OOP:一切皆对象,对象交互组成功能,功能叠加组成模块,模块叠加组成系统 类--砖头     系统--房子 类--细胞     系统--人 面向对象是非常适合做大型 ...

  2. Spring AOP 面向切面编程

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

  3. 大数据WEB阶段Spring框架 AOP面向切面编程(一)

    Spring - AOP面向切面编程(一) 一.代理模式概述 代理的特点:(目标对象即被代理者) 实现和目标对象相同的接口 具备和目标对象的方法 代理者不仅要做目标对象的方法 , 还要做一些额外的操作 ...

  4. 大数据WEB阶段Spring框架 AOP面向切面编程(二)

    Spring AOP面向切面编程(二) 一.切入点的execution表达式 execution的表达形式: execution(修饰符? 返回值类型 所在包类? 方法名(参数列表) 异常?) ?表示 ...

  5. spring中AOP(面向切面编程)

    spring中AOP(面向切面编程) 面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是spring框架中的一个重要内容 ...

  6. Spring AOP面向切面编程

    AOP面向切面编程: AOP(Aspect Oriented Programming),即面向切面编程,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公 ...

  7. 【SSM】Spring系列——AOP面向切面编程

    文章目录 03 AOP面向切面编程 3.1 AOP概述 3.2 面向切面编程对有什么好处 3.3 模拟AOP框架实现 3.3.1 代码实现版本一 3.3.2 代码实现版本二 3.3.3 代码实现版本三 ...

  8. Java绝地求生—Spring AOP面向切面编程

    Java绝地求生-Spring AOP面向切面编程 背景 动态代理 构建被代理对象 自动生成代理 调用动态代理 Spring方法 方式一:使用Spring的API接口 方式二:使用自定义类 方式三:使 ...

  9. java aop面向切面编程

    最近一直在学java的spring boot,一直没有弄明白aop面向切面编程是什么意思.看到一篇文章写得很清楚,终于弄明白了,原来跟python的装饰器一样的效果.http://www.cnblog ...

最新文章

  1. Python之路(第九篇)Python文件操作
  2. 干货,别再浪费时间到处找了,各大面试题和答案都在这里
  3. Hadoop/Spark生态圈里的新气象
  4. 利用水的浮力测量物体的重量,这个方法称象可靠吗?
  5. 分布式作业 Elastic Job 如何动态调整
  6. java验证身份证号码是否有效源代码
  7. 魔兽服务器联盟在线,《魔兽世界》怀旧服再开新服,部落联盟泾渭分明?
  8. 实现迭代服务器端和客户端
  9. 三角网导线平差实例_三角网条件平差计算
  10. bs结构管理系统 服务器多少钱,购买BS或CS架构的进销存软件哪个更划算
  11. 【愚公系列】2022年01月 Django商城项目16-用户中心-地址管理之省市三联动功能实现
  12. android 闪屏动态界面,Android实现闪屏欢迎界面
  13. SylixOS动态内存分配操作
  14. python中的图形界面设计_python图形化界面设计(tkinter)一全面介绍
  15. C#几行代码实现定时关机/重启 超详细(建议新手练习)
  16. Koa2仿知乎服务端项目:Webpack配置
  17. python3代码编程规范(命名、空格、注释、代码布局、编程建议等)
  18. (纪中)2246. 恐怖分子(gun)
  19. TDSQL:腾讯金融级分布式数据库解决方案
  20. 使用TextToSpeech语音读取

热门文章

  1. TeamCola - 最好用的团队工作日志软件
  2. 网络工程师必懂的专业术语!
  3. 让系统通过域用户自动打补丁
  4. linux网站爬取,Kali下httrack 爬取网站页面
  5. mysql存储过程日期类型_mysql中多种日期类型的格式话---用存储过程实现
  6. centos 7 mysql图形界面_centos7-vnstat图形界面搭建
  7. 什么是HystrixDashbord/如何使用?
  8. AOP 中必须明白的概念-切面(Aspect)
  9. notepad++ 远程连接阿里云服务器
  10. Bootstrap组件1_字体图标