15-Spring AOP的底层实现原理JDKProxyCGLIB
前一篇:14-Spring AOP编程https://blog.csdn.net/fsjwin/article/details/109480097
前面我们讨论动静态理的时候说过,想要实现动态代理需要满足三个条件:
- 目标对象
- 接口 代理对象和目标对象的相同接口
- 增强功能
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()方法,然后在前后进行加强。
也需要三个必要条件:
- 目标类
- 父类对象(接口)
- 增强代码
这点和jdkproxy一模一样,唯一不一样的是一个是接口、一个是一般的类
5.CGlib代码
- 目标类
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");}
}
- 测试类
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");}
}
- 测试结果
CjlibTest.intercept 前
StudentService.login
CjlibTest.intercept 后
6.另外一个大问题,那么这个代理对象实在什么时候创建的呢?
我们回头想想应该不难想到肯定实在BeanPostProcessor的时候被创建的,看下图:
- 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;}
}
- 配置文件
<?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>
- 测试
@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"));}
- 测试结果
@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代理的全部过程,代理均需要满足三个条件:
- 代理队形
- 接口(父类)
- 增强功能,
同时模拟了工厂在何时创建了代理对象就是在postProcessAfterInitialization的after方法的时候创建的。
下一篇:16-Spring 基于注解的AOP编程、AOP总结https://blog.csdn.net/fsjwin/article/details/109482768
15-Spring AOP的底层实现原理JDKProxyCGLIB相关推荐
- 底层实现_Java AOP的底层实现原理
AOP用于处理系统中分布于各个模块的横切关注点,比如事务管理.日志.缓存等. AOP实现的关键,在于AOP框架自动创建的AOP代理,AOP代理主要分为静态代理和动态代理,静态代理的代表为AspectJ ...
- (转)Spring AOP的底层实现技术
AOP概述 软件的编程语言最终的目的就是用更自然更灵活的方式模拟世界,从原始机器语言到过程语言再到面向对象的语言,我们看到编程语言在一步步用更自然.更强大的方式描述软件.AOP是软件开发思想的一个飞跃 ...
- Spring框架(一) 底层核心原理解析
感兴趣的话大家可以关注一下公众号 : 猿人刘先生 , 欢迎大家一起学习 , 一起进步 , 一起来交流吧! 说明 本系列文章以spring-framework-5.3.10为例 , 本篇文章的目的就是使 ...
- 【Spring AOP(2)篇】原理及两种实现方式(cglibjdk动态代理)
简介: Spring AOP(Aspect-Oriented Programming,面向切面编程)是 Spring 框架的一个重要特性,用于解耦和切割业务逻辑,是实现面向切面编程的重要手段之一.本文 ...
- Spring学习篇底层核心原理解析
说明 本系列文章以spring-framework-5.3.10为例 ,本篇文章的目的就是使各位读者能在使用Spring的基础上对Spring的一些比较核心的内容有一个大概的认识,并不是特别全面,会在 ...
- Spring aop 原始的工作原理的理解
理解完aop的名词解释,继续学习spring aop的工作原理. 首先明确aop到底是什么东西?又如何不违单一原则并实现交叉处理呢? 如果对它的认识只停留在面向切面编程,那就脏了.从oop(Objec ...
- 面试官:兄弟,说说 Spring Cloud 的底层架构原理吧
❤ Java极客技术,你值得星标的公众号 分布式系统面试系列02-Spring Cloud 的底层架构原理,前面我们讲了 前面我们讲了一个以Spring Cloud 技术栈实现的分布式系统,至少得包含 ...
- 什么是AOP,AOP的底层实现原理
什么是AOP?AOP的底层实现 1.什么是AOP AOP(Aspect Oritented Programing) 面向切面编程. AOP采取横向抽取机制,取代了传统的继承纵向继承体系的重复性代码(性 ...
- Spring - Dubbo的底层实现原理和机制
Dubbo :是一个RPC框架,SOA框架: Dubbo缺省协议采用单一长连接和NIO异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况. 作为RPC:支持各种 ...
最新文章
- Windows 10 不能安装更新 (0x8024402f)
- Lambda-常用函数式接口
- LeakCanary——直白的展现Android中的内存泄露
- logback logback.xml 常用配置详解
- java每天定时任务
- js页面传值php页面,php实现跳转传值有什么方法,js页面跳转传值
- STM32打印log--使用J-Link RTT Viewer
- mysql 1500万_【IT专家】mysql分表后 如何分页 (总共160个表1500万数据)
- iOS打包后收不到推送信息
- C++获取Unix时间戳(分别以秒和毫秒为单位)的几种方法
- 刘宇凡:从吃饭中的道理领悟SEO
- windows无法格式化u盘_如何解决u盘0字节无法格式化的问题
- java拼图游戏(带文档资料)
- 刚刚整理好-汉字转拼音缩写的函数(C#)
- linux系统进程有哪几种主要状态,Linux 进程状态详解
- jemalloc源码解读(六)基数树
- Cisco ❀ MPLS中的路由器角色
- padding有两种设置方式:
- Mysql 1607错误
- 【Bootstrap】bootstrap入门之栅格布局、弹性布局、组件类_02