首页 > 编程语言 >Spring源码(15) -- Aop动态代理之 Enhancer

Spring源码(15) -- Aop动态代理之 Enhancer

时间:2024-10-04 11:11:56浏览次数:1  
标签:Enhancer 15 Target create Object 源码 cglib public

Enhancer 用途

Enhancer (增强器) 是标准Jdk动态代理的替代品,用于生成动态子类以启用方法拦截,还允许代理扩展具体的基类。

原始且最通用的回调类型是 MethodInterceptor(方法拦截器)。

通常,每个 Enhancer 都会使用一个 Callback 回调,但可以使用 callbackFilter 控制每个方法使用哪个回调。

此类最常见的用途体现在静态辅助方法中。

对于高级需求,例如自定义要使用的 ClassLoader,应该创建一个新的Enhancer实例。CGLIB中的其他类遵循类似的模式。

所有增强的对象都实现Factory接口,除非使用setUseFactory显式禁用此功能。

Factory接口提供了一个API来更改现有对象的回调,并提供了一种更快速、更简单的方法来创建相同类型的新实例。

几乎可以替代java.lang.reflect.Proxy 类。

源码

org.springframework.cglib.proxy.Enhancer

Callback[]

源码:org.springframework.cglib.proxy.Callback

Callback[] 是回调数组,是Enhancer的属性之一。

public interface Callback {
}

CallbackFilter

源码:org.springframework.cglib.proxy.CallbackFilter

CallbackFilter ,也是Enhancer的属性之一。

CallbackFilter 就是 CallBack 的过滤器,callbackFilter 可以控制每个方法使用哪个 Callback 回调。

可以重写 callbackFilter 接口,并实现 accept()方法。

public interface CallbackFilter {
    int accept(Method var1);

    boolean equals(Object var1);
}

Enhancer示例

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;

public class EnhancerDemo {

    public static class Target {
        public void printHello() {
            System.out.println("Hello World");
        }
    }

    public static void main(String[] param) {
        //Enhancer 是标准Jdk动态代理的替代品,用于生成动态子类以启用方法拦截,还允许代理扩展具体的基类。
        Target proxy = (Target) Enhancer.create(Target.class, (MethodInterceptor) (p, method, args, methodProxy) -> {
            System.out.println("before method.");
            
            //以下 p的值是 com.example.demo.sourceCode.cglib.CglibDemo$Target$$EnhancerByCGLIB$$87c3a731@27c60c
            // methodProxy的 fastClassInfo 有 f1为 class com.example.demo.sourceCode.cglib.CglibDemo$Target, 
            // f2为class com.example.demo.sourceCode.cglib.CglibDemo$Target$$EnhancerByCGLIB$$87c3a731
            
            Object result = methodProxy.invokeSuper(p, args);  
            System.out.println("after method.");
            return result;
        });

        proxy.printHello();

    }

}

Enhancer的 create()方法

create()方法,可以创建被拦截对象的辅助方法。

    public static Object create(Class type, Callback callback) {
        Enhancer e = new Enhancer();
        //要扩展的类或要实现的接口
        e.setSuperclass(type);
        //设置回调数组
        e.setCallback(callback);
        return e.create();
    }
    
    
    
    /**
     *  必要时生成一个新类,并使用指定的回调(如果有的话)创建一个新的对象实例。使用超类的无参数构造函数。
     */
      public Object create() {
          classOnly = false;
          argumentTypes = null;
          return createHelper();
      }
      
      
      private Object createHelper() {
          preValidate();
          Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
                  ReflectUtils.getNames(interfaces),
                  filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter),
                  callbackTypes,
                  useFactory,
                  interceptDuringConstruction,
                  serialVersionUID);
          this.currentKey = key;
          
          //重点看这里, 调用了父类的 create() 方法
          Object result = super.create(key);
          return result;
    }
    
    

AbstractClassGenerator 的 create()

源码: org.springframework.cglib.core.AbstractClassGenerator#create

    protected Object create(Object key) {
        try {
          //获取类加载器
            ClassLoader loader = getClassLoader();
            Map<ClassLoader, ClassLoaderData> cache = CACHE;
            ClassLoaderData data = cache.get(loader);
            if (data == null) {
                synchronized (AbstractClassGenerator.class) {
                    cache = CACHE;
                    data = cache.get(loader);
                    if (data == null) {
                      //双重检查锁, 设置 ClassLoaderData。并设置缓存。
                        Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
                        data = new ClassLoaderData(loader);
                        newCache.put(loader, data);
                        CACHE = newCache;
                    }
                }
            }
            this.key = key;
            // 生成对象
            Object obj = data.get(this, getUseCache());
            if (obj instanceof Class) {
                return firstInstance((Class) obj);
            }
            return nextInstance(obj);
        }
        catch (RuntimeException | Error ex) {
            throw ex;
        }
        catch (Exception ex) {
            throw new CodeGenerationException(ex);
        }
    }

标签:Enhancer,15,Target,create,Object,源码,cglib,public
From: https://www.cnblogs.com/expiator/p/18446436

相关文章

  • CF154C题解
    传送门:https://codeforces.com/problemset/problem/154/C求出无向图中,满足所有出边都相连或出边直接连接点对的点对数。很显然可以暴力枚举点对一对对去check,时间复杂度\(O(n^2+m)\)。#include<bits/stdc++.h>usingnamespacestd;inlineintread(){charc;boo......
  • 【贪心】【二分】[NOIP2015]跳石头
    https://ac.nowcoder.com/acm/contest/22353/C正确的思路是二分查找+贪心。具体来说,可以通过二分来猜测一个最小的跳跃距离,然后通过贪心算法判断是否可以通过移除石头使所有的跳跃都满足这个最小跳跃距离。这种方法的核心是逐步逼近最优解,而不是直接删除前m小的元素。细节:在......
  • 【STC15】实现printf()重定向的相关问题
    本文前提:读者已经知道如何用STC15实现串口重定向的基础知识(大体思路和代码大意)。如果不知道,请移步:《STC15单片机-串口打印》:https://blog.csdn.net/weixin_46251230/article/details/126679956问题1:uint8_t 数字增长显示错误/*Privatevariables-------------------------......
  • 2024-3-13 气象中的常用代码 154828
    目录画图横坐标添加月份PythonMatlab空间映射标准化画图横坐标添加月份Pythonimportmatplotlib.pyplotaspltimportpandasaspdimportnumpyasnp#准备时间和温度数据start_date=pd.to_datetime('1996-12-01')#thenextdateend_date=pd.to_datetime('1998-......
  • 2023-12-15 博士挑战--达成 113823
    目录现状改进未来现状这个世界最神奇的,莫过于永远都有意外,第二步以和平的地方式提前达成了。1.意外一:迫于各种压力(我的态度、项目进度、其他学者进展、外界评价),导师已于上周开始给师姐改论文并尽快投出去。这结局是最好的,只是有点过早。2.意外二:没想到师妹论文写得太不勤快了,......
  • 2023-12-15 博士挑战--落幕 123744
    目录总纲现状反思未来总纲宇宙万物、世间一切自有因果。自助者天助,然若不自助,神明亦爱莫能助。人的好坏定义并非从言行举止来衡量,而是有无执着。现状老师不再执着于己见--要求他的所有学生都成为有声望的学者。我目前一切都好,正在做想做的理论方向且成就感满满,工资上涨,......
  • 2023-12-15 博士挑战--不完美达成 122918
    目录总纲现状反思未来总纲宇宙万物、世间一切自有因果。自助者天助,然若不自助,神明亦爱莫能助。人的好坏定义并非从言行举止来衡量,而是有无执着。现状老师也不会再强烈要求我们小组每个人都成为顶尖科学家了,也不会执着于己见了。我目前一切都好,正在做想做的理论方向且成......
  • [NOIP2015 提高组] 子串
    算法状态定义最初显然可以想到\(f[i][j][k]\)表示\(A\)串前\(i\)个,\(B\)串前\(j\)个,分割了\(k\)个子串但是这样无法递推\(k\)维于是加上一位\(f[i][j][k][0/1]\),最后一维表示是否选择\(A\)子串当前这一位,也就可以递推的计算状态转移当前位置不使......
  • 【开题报告】基于Springboot+vue农村住宅房屋信息管理应用系统(程序+源码+论文) 计算机
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着农村经济的快速发展和城乡一体化进程的加速推进,农村住宅房屋作为农村居民生活与生产的重要载体,其管理效率与信息化水平日益成为影响农村现代化建......
  • 20241002每日一题洛谷P1563
    粗看题目我靠,什么方向还变来变去的(哭泣核心思想:圈内右数,圈外左数为整体逆时针数;圈外右数,圈内左数为整体顺时针数运用结构体就有了第一版源码://///define_CRT_SECURE_NO_WARNINGS1include<stdio.h>includestructpeople{intface;charname[12];};intmain(){in......