什么是代理?

指为一个目标对象提供一个代理对象, 并由代理对象控制对目标对象的引用. 使用代理对象, 是为了在不修改目标对象的基础上, 增强目标对象的业务逻辑.

静态代理

静态代理的特点是, 为每一个业务增强都提供一个代理类, 由代理类来创建代理对象. 下面我们通过静态代理来实现对转账业务进行身份验证.

(1) 转账业务

public interface IAccountService {//主业务逻辑: 转账void transfer();
}
public class AccountServiceImpl implements IAccountService {@Overridepublic void transfer() {System.out.println("调用dao层,完成转账主业务.");}
}

(2) 代理类

public class AccountProxy implements IAccountService {//目标对象private IAccountService target;public AccountProxy(IAccountService target) {this.target = target;}/*** 代理方法,实现对目标方法的功能增强*/@Overridepublic void transfer() {before();target.transfer();}/*** 前置增强*/private void before() {System.out.println("对转账人身份进行验证.");}
}

(3) 测试

public class Client {public static void main(String[] args) {//创建目标对象IAccountService target = new AccountServiceImpl();//创建代理对象AccountProxy proxy = new AccountProxy(target);proxy.transfer();}
}结果:
对转账人身份进行验证.
调用dao层,完成转账主业务.

动态代理

静态代理会为每一个业务增强都提供一个代理类, 由代理类来创建代理对象, 而动态代理并不存在代理类, 代理对象直接由代理生成工具动态生成.

JDK动态代理

JDK动态代理是使用 java.lang.reflect 包下的代理类来实现. JDK动态代理动态代理必须要有接口.

(1) 转账业务

public interface IAccountService {//主业务逻辑: 转账void transfer();
}
public class AccountServiceImpl implements IAccountService {@Overridepublic void transfer() {System.out.println("调用dao层,完成转账主业务.");}
}

(2) 增强

因为这里没有配置切入点, 称为切面会有点奇怪, 所以称为增强.

public class AccountAdvice implements InvocationHandler {//目标对象private IAccountService target;public AccountAdvice(IAccountService target) {this.target = target;}/*** 代理方法, 每次调用目标方法时都会进到这里*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {before();return method.invoke(target, args);}/*** 前置增强*/private void before() {System.out.println("对转账人身份进行验证.");}
}

(3) 测试

public class Client {public static void main(String[] args) {//创建目标对象IAccountService target = new AccountServiceImpl();//创建代理对象IAccountService proxy = (IAccountService) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new AccountAdvice(target));proxy.transfer();}
}
结果:
对转账人身份进行验证.
调用dao层,完成转账主业务.

CGLIB动态代理

JDK动态代理必须要有接口, 但如果要代理一个没有接口的类该怎么办呢? 这时我们可以使用CGLIB动态代理. CGLIB动态代理的原理是生成目标类的子类, 这个子类对象就是代理对象, 代理对象是被增强过的.

注意: 不管有没有接口都可以使用CGLIB动态代理, 而不是只有在无接口的情况下才能使用.

(1) 转账业务

public class AccountService {public void transfer() {System.out.println("调用dao层,完成转账主业务.");}
}

(2) 增强

因为这里没有配置切入点, 称为切面会有点奇怪, 所以称为增强.

public class AccountAdvice implements MethodInterceptor {/*** 代理方法, 每次调用目标方法时都会进到这里*/@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {before();return methodProxy.invokeSuper(obj, args);//        return method.invoke(obj, args);  这种也行}/*** 前置增强*/private void before() {System.out.println("对转账人身份进行验证.");}
}

(3) 测试

public class Client {public static void main(String[] args) {//创建目标对象AccountService target = new AccountService();////创建代理对象AccountService proxy = (AccountService) Enhancer.create(target.getClass(),new AccountAdvice());proxy.transfer();}
}
结果:
对转账人身份进行验证.
调用dao层,完成转账主业务.

模拟Spring AOP场景

了解了动态代理后, 我们就可以自己来实现Spring AOP功能了, 所以下面我们来模拟下Spring AOP场景.

(1) 转账业务

public interface IAccountService {//主业务逻辑: 转账void transfer();
}
public class AccountServiceImpl implements IAccountService {@Overridepublic void transfer() {System.out.println("调用dao层,完成转账主业务.");}
}

(2) 切面抽象类

定义一个切面抽象类, 该类使用了模板方法的设计模式, 为开始, 结束, 异常, 前置增强, 后置增强提供了默认实现, 当我们定义切面类时只需要按需重写它们就行. isIntercept() 方法用来判断切入点是否正确, 切面类需要重写这个方法.

public abstract class BaseAspect implements MethodInterceptor {private static final Logger logger = LoggerFactory.getLogger(BaseAspect.class);@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object result = null;begin();try {if (isIntercept(method, args)) {before();result = methodProxy.invokeSuper(obj, args);after();} else {result = methodProxy.invokeSuper(obj,args);}} catch (Exception e) {logger.error("proxy failure", e);error(e);throw e;} finally {end();}return result;}/*** 开始增强*/public void begin() {}/*** 切入点判断*/public boolean isIntercept(Method method, Object[] args) throws Throwable {return true;}/*** 前置增强*/public void before() throws Throwable {}/*** 后置增强*/public void after() throws Throwable {}/*** 异常增强*/public void error(Throwable e) {}/*** 最终增强*/public void end() {}
}

(3) 切面类

创建一个切面类, 类中配置切入点和增强.

public class AccountAspect extends BaseAspect {/*** 切入点*/public boolean isIntercept(Method method, Object[] args) throws Throwable {return method.getName().equals("transfer");}/*** 前置增强*/public void before() throws Throwable {System.out.println("对转账人身份进行验证.");}
}

(4) 代理工厂类

定义一个工厂类来创建代理, 其实不创建这个类也行, 但为了模仿Spring还是创建了. @SuppressWarnings是为了抑制警告, 就是编译器上面的黄线.

public class ProxyFactory {@SuppressWarnings("unchecked")public static <T> T createProxy(final Class<?> targetClass, final MethodInterceptor methodInterceptor) {return (T) Enhancer.create(targetClass,methodInterceptor);}
}

(5) 测试

public class Client {public static void main(String[] args) {//创建目标对象IAccountService target = new AccountServiceImpl();//切面BaseAspect accountAspect = new AccountAspect();//创建代理对象IAccountService proxy = (IAccountService) ProxyFactory.createProxy(target.getClass(), accountAspect);proxy.transfer();}
}
结果:
对转账人身份进行验证.
调用dao层,完成转账主业务.

Spring AOP原理之动态代理相关推荐

  1. Spring AOP 概念及动态代理模式

    Spring AOP 概念及动态代理模式 文章目录 Spring AOP 概念及动态代理模式 1 AOP 的概念及相关术语 2 AOP 作用 3 AOP 原理概述 3.1 JDK 动态代理(Proxy ...

  2. Spring Boot实践——Spring AOP实现之动态代理

    Spring AOP 介绍 AOP的介绍可以查看 Spring Boot实践--AOP实现 与AspectJ的静态代理不同,Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改 ...

  3. AOP、ASPECT、Spring AOP、JDK动态代理、CGLib动态代理

    AOP.ASPECT.Spring AOP.JDK动态代理.CGLib动态代理 1 AOP介绍 1.1 基本定义 AOP(Aspect Oriented Programming)称为面向切面编程,它是 ...

  4. AOP原理之动态代理

    个人博客:https://suveng.github.io/blog/​​​​​​​ AOP原理之动态代理 实现AOP的底层是反射机制,其中有两种实现方式: 其一是JDK的动态代理: 其二是基于CGL ...

  5. spring AOP原理分析:静态代理;JDK实现接口动态代理;Cglib继承父类代理;SpringAop的责任链模式调用

    普通静态代理 代理类和真实类都需要实现同一个接口 接口 package com.fchan.layui.represent.service; /*** 静态代理demo*/ public interf ...

  6. Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理:

    ① JDK动态代理只提供接口的代理,不支持类的代理,要求被代理类实现接口.JDK动态代理的核心是InvocationHandler接口和Proxy类,在获取代理对象时,使用Proxy类来动态创建目标类 ...

  7. 关于Spring AOP,除了动态代理、CGLIB,你还知道什么?

    来源 | 草捏子 责编 | Carol 封图 | CSDN 付费下载于视觉中国 Spring 作为 Java 中最流行的框架,主要归功于其提供的 IOC 和 AOP 功能.本文将讨论 Spring A ...

  8. Spring——AOP操作 AspectJ动态代理方式

    有几天没有学习spring了,今天继续学习尚硅谷spring aop,讲的挺详细的,推荐去看看. 文章目录 一.准备工作 1.导入AspectJ依赖 2.切入点表达式 二 .配置文件实现 1.创建类( ...

  9. Spring AOP基础—JDK动态代理

    JDK动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler.其中InvocationHandler动态创建一个符合某一接口的实例,生成目标类 ...

  10. Spring AOP源码分析(四)Spring AOP的JDK动态代理

    2019独角兽企业重金招聘Python工程师标准>>> 本篇文章将会介绍上一个例子中的源码执行情况,从中熟悉整个SpringAOP的一些概念和接口设计. 首先整个SpringAOP的 ...

最新文章

  1. 2010河北职称计算机考试,2010年河北省职称计算机考试试题..doc
  2. golang mysql多表查询_MySQL多表查询
  3. android数据存放map_go语言学习笔记(18)-二维数组和map
  4. 字符串匹配算法(一):BF(BruteForce)算法和RK(RabinKarp)算法
  5. 每天一个linux命令(53)--ps命令
  6. 使用Git上传本地项目到oschina
  7. 深度学习(十五)基于级联卷积神经网络的人脸特征点定位
  8. cocos js响应过程
  9. parquet格式_数据工程101:揭开Hadoop数据格式的神秘面纱:Avro,ORC和Parquet
  10. java接口的关键字_java关键字-interface
  11. 《重构 改善既有代码的设计》笔记
  12. tomcat原理详解和请求过程(涉及网卡、套接字等)
  13. 神器!人工智能分离歌曲中的人声和背景音乐
  14. mysql 计算信度_解析组合信度CR、AVE值如何计算_组合信度cr
  15. 考勤系统(打卡时间计算)
  16. vue框架优点和缺点
  17. 数据分析师招聘岗位分析
  18. python-pyqt5-初识-2基本操作
  19. 从0入手使用dtree(超简单版)
  20. 【z】数字神经网络系统

热门文章

  1. linux查看cpu与内存
  2. C语言全局变量和数组的应用
  3. python绝对值编程_python求绝对值的三种方法小结
  4. 数组和集合有什么区别
  5. hexo+next主题美化
  6. 4.3.5 导频插入
  7. 今日头条 java笔试题_今日头条笔试第一题
  8. 基于php的人力资源管理系统,基于thinkPHP框架的人力资源管理系统
  9. JAVA类计算机专业毕业设计题目
  10. HTML5 QQ登录背景动态图片