当前位置: 首页 > news >正文

成都多享网站建设公司网站集约化建设意见

成都多享网站建设公司,网站集约化建设意见,手机网站制作案例,哈密建设厅网站目录 一、问题描述二、原因分析三、解决方案1#xff08;推荐#xff09;#xff1a;获取线程上下文中的类加载器扩展 四、解决方案2#xff1a;自定义SpringBoot类加载器 一、问题描述 在使用Byte-Buddy中的TypePool对类进行扩展后#xff0c;在本地开发集成环境#x… 目录 一、问题描述二、原因分析三、解决方案1推荐获取线程上下文中的类加载器扩展 四、解决方案2自定义SpringBoot类加载器 一、问题描述 在使用Byte-Buddy中的TypePool对类进行扩展后在本地开发集成环境Intellij Idea中可以正常运行其中被扩展的类com.xx.yourClass是某个maven 依赖中的类在开发环境没法直接进行编辑具体扩展代码示例如下 //使用TypePool Redefine扩展属性 TypePool typePool TypePool.Default.ofSystemLoader(); Class bar new ByteBuddy().redefine(typePool.describe(com.xx.yourClass).resolve(), ClassFileLocator.ForClassLoader.ofSystemLoader()).defineField(qux, String.class) .make().load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.INJECTION).getLoaded(); Field quxField bar.getDeclaredField(qux); Assert.isTrue(Objects.nonNull(quxField), qux field is null);但是通过SpringBoot打包底层依赖spring-boot-maven-plugin进行打包成jar后运行jar报如下错误即无法加载到被扩展的类某个maven依赖中的类 # 使用TypePool报错 net.bytebuddy.pool.TypePool$Resolution$NoSuchTypeException: Cannot resolve type description for com.xxx.YourClass # 扩展 - 使用Redefine可能会报如下错误 java.lang.IllegalStateException: Could not locate class file for com.xxx.YourClass二、原因分析 可以发现上述示例代码中有3处使用了系统类加载器 TypePool typePool TypePool.Default.ofSystemLoader() refedine(.., ClassFileLocator.ForClassLoader.ofSystemLoader()) load(ClassLoader.getSystemClassLoader(), ...)问题就出在这块SpingBoot打包后的Jar文件有其特殊的层次结构无法通过系统的类加载器加载到内嵌jar即/BOOT-INF/lib/*.jar中的类而是需要通过SpringBoot自身提供的类加载器org.springframework.boot.loader.launch.LaunchedClassLoader进行加载所以如上代码通过系统类加载器SystemClassLoader是无法加载到内嵌jar中的类的。 SpringBoot打包后的Jar文件结构示例如下 三、解决方案1推荐获取线程上下文中的类加载器 具体的解决方法就是如何获取并设置byte-buddy使用SpringBoot自身提供的类加载器org.springframework.boot.loader.launch.LaunchedClassLoader可以通过个取巧的方式获取SpringBoot的类加载器。 在应用中植入如下代码即分别获取线程上下文中的类加载器、系统加载器、平台加载器 System.out.println(Thread.CurrentThread.ContextClassLoader Thread.currentThread().getContextClassLoader().getClass().getName()); System.out.println(SystemClassLoader ClassLoader.getSystemClassLoader().getClass().getName()); System.out.println(PlatformClassLoader ClassLoader.getPlatformClassLoader().getClass().getName());直接在本地开发集成环境Intellij Idea中执行打印结果如下 Thread.CurrentThread.ContextClassLoaderjdk.internal.loader.ClassLoaders$AppClassLoader SystemClassLoaderjdk.internal.loader.ClassLoaders$AppClassLoader PlatformClassLoaderjdk.internal.loader.ClassLoaders$PlatformClassLoader通过SpringBoot打包成Jar运行Jar后打印结果如下 Thread.CurrentThread.ContextClassLoaderorg.springframework.boot.loader.launch.LaunchedClassLoader SystemClassLoaderjdk.internal.loader.ClassLoaders$AppClassLoader PlatformClassLoaderjdk.internal.loader.ClassLoaders$PlatformClassLoader可以发现在运行SpringBoot Jar后SpringBoot会将线程上下文中的类加载器即Thread.currentThread().getContextClassLoader()设置为SpringBoot自身的类加载器LaunchedClassLoader如此即可通过获取线程上下文中的类加载器的方式来兼容本地开发环境和SpringBoot Jar中的类都能被正确加载。 调整最开始的示例代码将所有使用系统类加载器的地方都调整为使用线程上下文中的类加载器调整后代码如下 //调整1获取SpringBoot内置的类加载器 ClassLoader contextClassLoader Thread.currentThread().getContextClassLoader(); ClassFileLocator springBootClassFileLocator ClassFileLocator.ForClassLoader.of(contextClassLoader); //调整2使用线程上下文中的SpringBoot内置的类加载器 TypePool typePool TypePool.Default.of(springBootClassFileLocator); Class bar new ByteBuddy().redefine(typePool.describe(com.xx.yourClass).resolve(), //调整3使用线程上下文中的SpringBoot内置的类加载器springBootClassFileLocator).defineField(qux, String.class) .make()//调整4使用线程上下文中的SpringBoot内置的类加载器.load(contextClassLoader, ClassLoadingStrategy.Default.INJECTION).getLoaded(); Field quxField bar.getDeclaredField(qux); Assert.isTrue(Objects.nonNull(quxField), qux field is null);搞定 扩展 如果不使用TypePool而是普通的redefine、rebase等操作此时是可以直接获取到被扩展的类的xx.class而不是类的字符串表示注意这时只需将所有跟类加载器相关的统一调整为根据被扩展类进行获取即可如下示例统一根据被扩展类YourClass获取类加载器 ByteBuddyAgent.install(); new ByteBuddy().redefine(YourClass.class, ClassFileLocator.ForClassLoader.of(YourClass.class.getClassLoader()))//省略....make().load(YourClass.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());四、解决方案2自定义SpringBoot类加载器 大力出奇迹可以在byte-buddy中自定义SpringBoot的类加载器实现 具体参见https://github.com/raphw/byte-buddy/issues/1470#issuecomment-1617556513 即自行遍历/BOOT-INF/**/*.jar的所有jar来加载类具体自定义SpringBootClassFileLocator 实现代码如下 import net.bytebuddy.dynamic.ClassFileLocator; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver;import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.List;/*** SpringBoot复合类加载器** author luohq* date 2025-04-24* link a hrefhttps://github.com/raphw/byte-buddy/issues/1470#issuecomment-1617556513https://github.com/raphw/byte-buddy/issues/1470#issuecomment-1617556513/a*/ public class SpringBootClassFileLocator {private SpringBootClassFileLocator() {}/*** 获取SpringBoot复合类加载器** return SpringBoot复合类加载器*/public static ClassFileLocator ofCompound() {try {String basePath SpringBootClassFileLocator.class.getResource(/).getPath();ListClassFileLocator classFileLocators new ArrayListClassFileLocator();classFileLocators.add(ClassFileLocator.ForClassLoader.ofSystemLoader());if (basePath ! null basePath.contains(BOOT-INF)) {String matchPattern ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX /BOOT-INF/**/*.jar;ResourcePatternResolver resourcePatternResolver new PathMatchingResourcePatternResolver();Resource[] resources resourcePatternResolver.getResources(matchPattern);for (Resource resource : resources) {ClassFileLocator classFileLocator transform(resource);if (classFileLocator ! null) {classFileLocators.add(classFileLocator);}}} else {classFileLocators.add(ClassFileLocator.ForClassLoader.ofPlatformLoader());}return new ClassFileLocator.Compound(classFileLocators);} catch (IOException ioe) {throw new RuntimeException(Init SpringBoot ClassFileLocator Exception!, ioe);}}/*** 转换资源为ClassFileLocator** param resource 资源* return ClassFileLocator* throws IOException IO异常*/private static ClassFileLocator transform(Resource resource) throws IOException {try (InputStream inputStream resource.getInputStream()) {if (inputStream ! null) {if (resource.getFilename().endsWith(jar)) {File tempFile File.createTempFile(temp/jar/ resource.getFilename(), .jar);Files.copy(inputStream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);return ClassFileLocator.ForJarFile.of(tempFile);}}}return null;} }SpringBootClassFileLocator 集成示例如下 ClassLoader contextClassLoader Thread.currentThread().getContextClassLoader(); //调整使用自定义的SpringBoot类加载器 ClassFileLocator springBootClassFileLocator SpringBootClassFileLocator.ofCompound(); TypePool typePool TypePool.Default.of(springBootClassFileLocator); Class bar new ByteBuddy().redefine(typePool.describe(com.xx.yourClass).resolve(), springBootClassFileLocator).defineField(qux, String.class) .make().load(contextClassLoader, ClassLoadingStrategy.Default.INJECTION).getLoaded(); Field quxField bar.getDeclaredField(qux); Assert.isTrue(Objects.nonNull(quxField), qux field is null);实际测试加载速度不如解决方案1且还需额外维护SpringBootClassFileLocator 实现综合对比还是更推荐解决方案1解决方案2可以作为一个备选方案。
http://www.zqtcl.cn/news/329027/

相关文章:

  • 打开网站说建设中是什么问题网站开发收税
  • 海口建设厅网站grimhelm wordpress
  • 如何快速提升网站pr淮北房产网
  • 微网站和微信广州营销型网站建设团队
  • 企业网站制作托管微信建站网站
  • h5网站如何做排名济南网站建设选聚搜网络
  • 网站建设 手机wordpress 仿煎蛋主题
  • 织梦可以仿所有网站吗电子商务网站建设臧良运课后答案
  • 怎样创建个人购物网站wordpress没有外观
  • 衡水手机网站建设公司计算机大专学历有用吗
  • 有哪些网站做的很好桐乡市建设局官方网站
  • 做公众号和网站一样吗免费正能量网站下载ww
  • 使用帝国做软件下载网站源码顺义区做网站的公司
  • 网站用什么颜色成都网站建设公司服务
  • 重庆手机网站方案设计凡科建站网站怎么保存发给别人
  • 北京住房建设官方网站xampp wordpress服务器
  • 卖衣服的网站建设素材网站免费短视频
  • 萍乡网站建设哪家公司好搜索引擎推广预算
  • 如何做网站不容易被攻击网站定位策划书
  • 自己做网站去哪买服务器多说wordpress
  • 网站排名突然没有了网站开发背景图
  • 比较容易做流量的网站设计模板素材网站
  • 电商网站建设 网站定制开发兰州展柜公司网站建设
  • 临沂城乡建设管理局网站腾讯体育
  • 一个空间怎么放两个网站ps个人网站首页怎么制作
  • 云南通耀建设工程有限公司网站国际购物网站平台有哪些
  • 网站建设外包服务上海网站建设公司怎么分辨好坏
  • 建筑类企业网站模板下载微信搜索推广
  • 上海网站备案在哪里wordpress短链接关键字
  • 金诚财富网站是谁做的建站技术博客