spring - 如何在springboot中使用自定义的自定义类加载器
问题描述
如何在 Spring Boot 中使用自定义类加载器加载 bean
我需要加密 spring boot 项目。
起初我尝试使用proguard,但失败了,因为 spring 使用了很多 Annotations 并且它有DI。
然后我尝试使用自定义类加载器。我想先加密我的类文件,然后使用我的自定义类加载器加载加密的类文件,然后解密。</p>
这是我的演示:https ://github.com/CaiBaoHong/boot-by-custom-loader
启动时失败:
ConfigServletWebServerApplicationContext :
Exception encountered during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'methodValidationPostProcessor' defined in class path resource
[org/springframework/boot/autoconfigure/validation/ValidationAutoConfiguration.class]:
Unsatisfied dependency expressed through method 'methodValidationPostProcessor' parameter 0;
nested exception is
org.springframework.beans.factory.CannotLoadBeanClassException:
Error loading class [com.abc.bootbycustomloader.controller.UserController]
for bean with name 'userController' defined in file
[D:\code\boot-by-custom-loader\out\production\classes\com\abc\bootbycustomloader\controller\UserController.class]: problem with class file or dependent class;
nested exception is java.lang.LinkageError: loader (instance of com/abc/bootbycustomloader/loader/MyClassLoader):
attempted duplicate class definition for name:
"com/abc/bootbycustomloader/controller/UserController"
@SpringBootApplication
public class ServerApplication {
public static void main(String[] args) {
MyResourceLoader rLoader = new MyResourceLoader();
SpringApplication app = new SpringApplicationBuilder().build();
app.addPrimarySources(Arrays.asList(ServerApplication.class));
app.setResourceLoader(rLoader);
app.run(args);
}
}
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/hello")
public String hello(){
System.out.println("hello hello hello...");
return "hello";
}
}
public class MyResourceLoader extends DefaultResourceLoader {
private ClassLoader cl = new MyClassLoader();
@Override
public Resource getResource(String location) {
System.out.println("getResource: "+location);
return super.getResource(location);
}
@Override
public ClassLoader getClassLoader() {
return cl;
}
}
public class MyClassLoader extends ClassLoader {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (name.equals("com.abc.bootbycustomloader.controller.UserController")) {
// assump that UserController is the encrypted class
// i need to load this encrypted class, and decrypted it!
System.out.println("!!!!!encrypted!!!!! : " + name);
// load the class from a special place, mock the decrypted processing
String path = "D:\\_clz\\UserController.class";
byte[] data = new byte[0];
try {
data = Files.readAllBytes(Paths.get(path));
} catch (IOException e) {
e.printStackTrace();
}
// mock decrypted processing success, return the decrypted class
Class<?> clz = defineClass(name, data, 0, data.length);
return clz;
} else {
// assump that other class is not encrypted class
// just load it as usual
return super.loadClass(name);
}
}
}
解决方案
推荐阅读
- javascript - 我可以让 Vue.js 跨站点保持活跃吗?
- javascript - 如何知道谁调用了控制器
- openlayers - 在 Openlayers 上表示高度的好方法?
- python - REDIS BGSAVE 断言失败,由信号 6 终止。(macos / python)
- excel - 使用用户定义的函数通过 ParamArray 传递数组
- reactjs - antd table,禁用列的未排序选项(强制排序)
- aframe - 如何在 A-Frame 中同时支持多种类型的 VR 控制器?
- java - 如何将字符串转换为 Json 并从中提取信息
- c# - 重新运行程序,得到不同的结果 C# UWP vs2019
- java - 如何为单个 C 函数生成多个包装器?