首页 > 解决方案 > 如何在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);
        }
    }
}

标签: springspring-bootencryptionclassloaderobfuscation

解决方案


推荐阅读