AOP底层实现原理

devtools/2024/10/23 18:22:34/

一、JDK

  • 核心思想:
    原始类和代理类实现相同的接口

使用JDK自带api创建动态代理

java">public class JDKTest{public static void main(String[] args){// 获取原始对象UserService userService = new UserServiceImpl();ClassLoader classLoader = JDKTest.class.getClassLoader();Class<?>[] interfaces = userService.getClass().getInterfaces();InvocationHandler invocationHandler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("====执行原始方法之前====");// 运行原始方法Object ret = method.invoke(userService, args);System.out.println("====执行原始方法之后====");return ret;}};UserService userServiceProxy = (UserService)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);userServiceProxy.register(new User());userServiceProxy.login("zhl", "123");}
}
  1. 类加载器的作用(ClassLoader)
    类加载器把对应类的字节码文件(.class)加载到JVM,创建这个类的Class对象,进而创建这个类的对象。
    动态字节码技术没有创建代理类的源文件和字节码文件,但是需要创建动态代理类的对象,所以需要借用一个类加载器。
  2. interfaces
    原始类实现的接口
  3. InvocationHandler
    为原始类中的原始方法添加额外功能

二、Cglib

  • 核心思想:
    代理类继承原始类

使用Cglib创建动态代理,创建过程大致和JDK方式类似

java">public class CglibTest {public static void main(String[] args) {// 原始对象UserService userService = new UserService();Enhancer enhancer = new Enhancer();// 为动态代理类设置类加载器enhancer.setClassLoader(CglibTest.class.getClassLoader());// 设置原始类为父类,添加额外功能enhancer.setSuperclass(userService.getClass());MethodInterceptor interceptor = new MethodInterceptor() {@Overridepublic Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("----------cglib before--------");Object ret = method.invoke(userService, args);System.out.println("----------cglib after--------");return ret;}};// callback <===> invocationHandlerenhancer.setCallback(interceptor);// 创建代理对象UserService serviceProxy = (UserService) enhancer.create();serviceProxy.login("zzz", "222");serviceProxy.register(new User());}
}

三、BeanPostProcessor

Spring工厂如何加工原始对象?
思路分析:
在这里插入图片描述
简单代码实现:

java">public class ProxyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {InvocationHandler invocation = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("--------核心功能之前---------");Object ret = method.invoke(bean, args);System.out.println("--------核心功能之后---------");return ret;}};return Proxy.newProxyInstance(ProxyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(),invocation);}
}
<bean id="userService" class="com.zhl.factory.UserServiceImpl"/>
<!--对当前配置文件中的所有bean进行加工-->
<bean id="proxyBeanPostProcessor" class="com.zhl.factory.ProxyBeanPostProcessor"/>

这里的实现比较粗糙,没有引入切入点,对整个Spring工厂中的bean都进行了加工。


http://www.ppmy.cn/devtools/39381.html

相关文章

idea 新建spring maven项目、ioc和依赖注入

文章目录 一、新建Spring-Maven项目二、在Spring-context使用IOC和依赖注入 一、新建Spring-Maven项目 在pom.xml文件中添加插件管理依赖 <build><plugins><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.1</ver…

前后端分离遇到CORS问题的解决办法

用一个简单的前后端分离项目中讲解CORS 前端代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">&…

Unity TileMap入门

概述 相信很多同学学习制作游戏都是从2D游戏开始制作的吧&#xff0c;瓦片地图相信大家都有接触&#xff0c;那接下来让我们学习一下这部分的内容吧&#xff01; Tilemap AnimationFrameRate:设置每帧动画的播放速率。Color:瓦片地图的颜色TileAnchor:锚点&#xff0c;&#x…

设计模式——代理模式(Proxy)

代理模式&#xff08;Proxy Pattern&#xff09;是程序设计中的一种设计模式&#xff0c;其核心概念是为一个对象提供一个代理&#xff0c;以控制对这个对象的访问。在某些情况下&#xff0c;一个对象不适合或者不能直接引用另一个对象&#xff0c;此时可以通过一个代理对象来实…

Vue从入门到实战Day03

一、生命周期 1. 生命周期四个阶段 思考&#xff1a; ①什么时候可以发送初始化渲染请求&#xff1f; 答&#xff1a;越早越好&#xff0c;在创建阶段后 ②什么时候可以开始操作DOM&#xff1f; 答&#xff1a;至少DOM得渲染出来&#xff0c;在挂载阶段结束后。 Vue生命周…

[力扣题解]455. 分发饼干

题目&#xff1a;455. 分发饼干 思路 贪心法 代码 class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {int cookie_i, belly_i, result 0;// 满足的小孩数 : result// 胃口: g// 饼干: ssort(g.begin(), g.end());so…

Java算法-力扣leetcode-14. 最长公共前缀

14. 最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 ""。 示例 1&#xff1a; 输入&#xff1a; strs ["flower","flow","flight"] 输出&#xff1a; "fl"示…

字符以及字符串函数

字符以及字符串函数 求字符串长度strlen 长度不受限制的字符串函数strcpystrcatstrcmp 长度受限制的字符串函数strncpystrncatstrncmp 字符串查找strstrstrtok 错误信息报告strerror 字符分类函数字符转换函数tolowertoupper 内存操作函数memcpymemmovememcmpmemset 这篇文章注…