前一篇:14-Spring AOP编程https://blog.csdn.net/fsjwin/article/details/109480097
前面我们讨论动静态理的时候说过,想要实现动态代理需要满足三个条件:

  1. 目标对象
  2. 接口 代理对象和目标对象的相同接口
  3. 增强功能

1.JDK proxy动态代理原理

先来对jdk的proxy底层原理进行分析。
通过下面一幅图,应该可以对jdkproxy的代理细节有个深入的认识:

2.JDK proxy代码

JDKProxy.java

package proxy.jdk;import proxy.service.UserService;
import proxy.service.impl.UserServiceImpl;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** @author yuhl* @Date 2020/11/3 22:23* @Classname JDKProxy* @Description JDK动态代理*/
public class JDKProxy {public static void main(String[] args) {//目标对象UserService userService = new UserServiceImpl();InvocationHandler invocationHandler = new InvocationHandler() {/**** @param proxy 代理对象,暂时不用* @param method 需要被增强的方法* @param args 方法的返回值后* @return 原方法的返回值* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("JDKProxy.invoke 前增强");Object ret = method.invoke(userService, args);System.out.println("JDKProxy.invoke 后增强");return ret;}};UserService userServiceProxy = (UserService)Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), invocationHandler);userService.login("yuhl", "1111");userServiceProxy.login("yuhl", "1111");}
}

3.JDK proxy学习这个动态代理有什么意义呢?

前面我们学习了MethodInterceptor,他和jdkproxy什么关系呢?一个是sun对动态dialing的实心,另一个是aop联盟的实现。aop联盟的实现更为友好吧。

学习这个jdkproxy有什么意义呢?
意义就在于spring的底层就是使用的这个方法生成的proxy对象返回给我们的。这样我们就知道了spring生成代理对象的源码。对于门写代码有很好的的撑腰作用。

4.CGlib动态代理

和JDK动态代理一样,cglib可以对一般的类惊醒动态代理,但是他的条件适应的,他的底层是集成了当前类,然后用super.login()方法,然后在前后进行加强。
也需要三个必要条件:

  1. 目标类
  2. 父类对象(接口)
  3. 增强代码
    这点和jdkproxy一模一样,唯一不一样的是一个是接口、一个是一般的类

5.CGlib代码

  1. 目标类
package proxy.cglib;import proxy.service.User;/*** @author yuhl* @Date 2020/11/3 23:00* @Classname StudentService* @Description TODO*/
public class StudentService {public boolean login(String name,String password){System.out.println("StudentService.login");return true;}public void register(User user) {System.out.println("StudentService.register");}
}
  1. 测试类
package proxy.cglib;import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** @author yuhl* @Date 2020/11/3 23:01* @Classname CjlibTest* @Description TODO*/
public class CjlibTest {public static void main(String[] args) {//目标类StudentService studentService = new StudentService();Enhancer enhancer = new Enhancer();enhancer.setSuperclass(studentService.getClass());enhancer.setClassLoader(CjlibTest.class.getClassLoader());MethodInterceptor methodInterceptor= new MethodInterceptor() {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("CjlibTest.intercept 前");Object rev = method.invoke(studentService,objects);System.out.println("CjlibTest.intercept 后");return rev;}};enhancer.setCallback(methodInterceptor);StudentService studentServiceProxy = (StudentService) enhancer.create();studentServiceProxy.login("zhangsan", "211111");//studentServiceProxy.login("yuhl", "3333");}
}
  1. 测试结果
CjlibTest.intercept 前
StudentService.login
CjlibTest.intercept 后

6.另外一个大问题,那么这个代理对象实在什么时候创建的呢?

我们回头想想应该不难想到肯定实在BeanPostProcessor的时候被创建的,看下图:

  1. ProxyBeanPostProcessor.java代码
package proxy.service;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** @author yuhl* @Date 2020/11/3 23:31* @Classname ProxyBeanPostProcessor* @Description 模拟spring底层生成代理对象的过程*/
public class ProxyBeanPostProcessor implements BeanPostProcessor {proxy.service.UserService userService = new proxy.service.impl.UserServiceImpl();@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}/**** @param bean 被修改的bean* @param beanName* @return* @throws BeansException*/@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return Proxy.newProxyInstance(this.getClass().getClassLoader(), userService.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("ProxyBeanPostProcessor.invoke 前----------》");Object rev = method.invoke(userService, args);System.out.println("ProxyBeanPostProcessor.invoke 后----------》");return rev;}});// return bean;}
}
  1. 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"><bean id="userService" class="proxy.service.impl.UserServiceImpl"/><!--模拟spring生成代理对象的过程--><bean id="proxyBeanPostProcessor" class="proxy.service.ProxyBeanPostProcessor"/></beans>
  1. 测试
    @Testpublic void test5() {ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext7.xml");proxy.service.UserService userService = (proxy.service.UserService)ctx.getBean("userService");userService.login("zhangsan","111111");userService.regester(new User(2, "222222"));}
  1. 测试结果
    @Testpublic void test5() {ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext7.xml");proxy.service.UserService userService = (proxy.service.UserService)ctx.getBean("userService");userService.login("zhangsan","111111");userService.regester(new User(2, "222222"));}

7.总结

到此我们明白了jdk代理和cglib代理的全部过程,代理均需要满足三个条件:

  1. 代理队形
  2. 接口(父类)
  3. 增强功能,
    同时模拟了工厂在何时创建了代理对象就是在postProcessAfterInitialization的after方法的时候创建的。

下一篇:16-Spring 基于注解的AOP编程、AOP总结https://blog.csdn.net/fsjwin/article/details/109482768

15-Spring AOP的底层实现原理JDKProxyCGLIB相关推荐

  1. 底层实现_Java AOP的底层实现原理

    AOP用于处理系统中分布于各个模块的横切关注点,比如事务管理.日志.缓存等. AOP实现的关键,在于AOP框架自动创建的AOP代理,AOP代理主要分为静态代理和动态代理,静态代理的代表为AspectJ ...

  2. (转)Spring AOP的底层实现技术

    AOP概述 软件的编程语言最终的目的就是用更自然更灵活的方式模拟世界,从原始机器语言到过程语言再到面向对象的语言,我们看到编程语言在一步步用更自然.更强大的方式描述软件.AOP是软件开发思想的一个飞跃 ...

  3. Spring框架(一) 底层核心原理解析

    感兴趣的话大家可以关注一下公众号 : 猿人刘先生 , 欢迎大家一起学习 , 一起进步 , 一起来交流吧! 说明 本系列文章以spring-framework-5.3.10为例 , 本篇文章的目的就是使 ...

  4. 【Spring AOP(2)篇】原理及两种实现方式(cglibjdk动态代理)

    简介: Spring AOP(Aspect-Oriented Programming,面向切面编程)是 Spring 框架的一个重要特性,用于解耦和切割业务逻辑,是实现面向切面编程的重要手段之一.本文 ...

  5. Spring学习篇底层核心原理解析

    说明 本系列文章以spring-framework-5.3.10为例 ,本篇文章的目的就是使各位读者能在使用Spring的基础上对Spring的一些比较核心的内容有一个大概的认识,并不是特别全面,会在 ...

  6. Spring aop 原始的工作原理的理解

    理解完aop的名词解释,继续学习spring aop的工作原理. 首先明确aop到底是什么东西?又如何不违单一原则并实现交叉处理呢? 如果对它的认识只停留在面向切面编程,那就脏了.从oop(Objec ...

  7. 面试官:兄弟,说说 Spring Cloud 的底层架构原理吧

    ❤ Java极客技术,你值得星标的公众号 分布式系统面试系列02-Spring Cloud 的底层架构原理,前面我们讲了 前面我们讲了一个以Spring Cloud 技术栈实现的分布式系统,至少得包含 ...

  8. 什么是AOP,AOP的底层实现原理

    什么是AOP?AOP的底层实现 1.什么是AOP AOP(Aspect Oritented Programing) 面向切面编程. AOP采取横向抽取机制,取代了传统的继承纵向继承体系的重复性代码(性 ...

  9. Spring - Dubbo的底层实现原理和机制

    Dubbo :是一个RPC框架,SOA框架: Dubbo缺省协议采用单一长连接和NIO异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况. 作为RPC:支持各种 ...

最新文章

  1. Windows 10 不能安装更新 (0x8024402f)
  2. Lambda-常用函数式接口
  3. LeakCanary——直白的展现Android中的内存泄露
  4. logback logback.xml 常用配置详解
  5. java每天定时任务
  6. js页面传值php页面,php实现跳转传值有什么方法,js页面跳转传值
  7. STM32打印log--使用J-Link RTT Viewer
  8. mysql 1500万_【IT专家】mysql分表后 如何分页 (总共160个表1500万数据)
  9. iOS打包后收不到推送信息
  10. C++获取Unix时间戳(分别以秒和毫秒为单位)的几种方法
  11. 刘宇凡:从吃饭中的道理领悟SEO
  12. windows无法格式化u盘_如何解决u盘0字节无法格式化的问题
  13. java拼图游戏(带文档资料)
  14. 刚刚整理好-汉字转拼音缩写的函数(C#)
  15. linux系统进程有哪几种主要状态,Linux 进程状态详解
  16. jemalloc源码解读(六)基数树
  17. Cisco ❀ MPLS中的路由器角色
  18. padding有两种设置方式:
  19. Mysql 1607错误
  20. 【Bootstrap】bootstrap入门之栅格布局、弹性布局、组件类_02

热门文章

  1. 不用再往下划,信息熵(Entropy)概念及应用(附视频)都在这里啦!
  2. mysql数据迁移_Mysql数据迁移方法
  3. Mysql数据迁移到达梦数据库
  4. Multicast Routing
  5. 摩托罗拉Razr3配置怎么样 摩托罗拉Razr3何时上市
  6. three.js学习二
  7. hdu_2570_配置解药_存疑
  8. Linux 查看网关gateway方法
  9. 孕期做什么副业好?在家兼职挣钱的孕妇不仅能很好地抚养孩子,还能继续她们的职业生涯
  10. Oracle:11g服务详细介绍及,哪些服务是必须开启的