如何在springboot中使用自定义类加载器

如何在springboot中使用自定义类加载器,spring,spring-boot,encryption,classloader,obfuscation,Spring,Spring Boot,Encryption,Classloader,Obfuscation,如何在spring boot中使用自定义类加载器加载bean 我需要加密spring boot项目 起初我尝试使用proguard,但失败了,因为spring使用了大量注释,并且它有DI 然后我尝试使用自定义类加载器。我想先加密我的类文件,然后使用我的自定义类加载器加载加密的类文件,然后解密它 这是我的演示: 当它启动时,它会失败: ConfigServletWebServerApplicationContext : Exception encountered during context

如何在spring boot中使用自定义类加载器加载bean

我需要加密spring boot项目

起初我尝试使用proguard,但失败了,因为spring使用了大量注释,并且它有DI

然后我尝试使用自定义类加载器。我想先加密我的类文件,然后使用我的自定义类加载器加载加密的类文件,然后解密它

这是我的演示:

当它启动时,它会失败:

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"

@springboot应用程序
公共类服务器应用程序{
公共静态void main(字符串[]args){
MyResourceLoader rLoader=新的MyResourceLoader();
SpringApplication app=新建SpringApplicationBuilder().build();
app.addPrimarySources(Arrays.asList(ServerApplication.class));
应用程序setResourceLoader(rLoader);
应用程序运行(args);
}
}
@RestController
@请求映射(“/user”)
公共类用户控制器{
@请求映射(“/hello”)
公共字符串hello(){
System.out.println(“你好…”);
回复“你好”;
}
}
公共类MyResourceLoader扩展了DefaultResourceLoader{
私有类加载器cl=新的MyClassLoader();
@凌驾
公共资源getResource(字符串位置){
System.out.println(“getResource:+位置”);
返回super.getResource(位置);
}
@凌驾
公共类加载器getClassLoader(){
返回cl;
}
}
公共类MyClassLoader扩展了ClassLoader{
@凌驾
公共类loadClass(字符串名称)引发ClassNotFoundException{
if(name.equals(“com.abc.bootbycustomloader.controller.UserController”)){
//假设UserController是加密类
//我需要加载这个加密类,并解密它!
System.out.println(“!!!!!加密!!!!!!!:”+名称);
//从特殊位置加载类,模拟解密处理
String path=“D:\\\\u clz\\UserController.class”;
字节[]数据=新字节[0];
试一试{
data=Files.readAllBytes(path.get(path));
}捕获(IOE异常){
e、 printStackTrace();
}
//模拟解密处理成功,返回解密的类
类clz=defineClass(名称,数据,0,数据.length);
返回clz;
}否则{
//假设另一个类不是加密类
//照常装就行了
返回super.loadClass(名称);
}
}
}
@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);
        }
    }
}