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

Po *_*hoi 5 encryption obfuscation spring classloader spring-boot

如何在 Spring Boot 中使用自定义类加载器加载 bean

\n\n

我需要加密 Spring Boot 项目。

\n\n

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

\n\n

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

\n\n

这是我的演示: https: //github.com/CaiBaohong/boot-by-custom-loader

\n\n

启动时失败:

\n\n
ConfigServletWebServerApplicationContext : \n  Exception encountered during context initialization - cancelling refresh attempt: \n    org.springframework.beans.factory.UnsatisfiedDependencyException: \n      Error creating bean with name \'methodValidationPostProcessor\' defined in class path resource \n        [org/springframework/boot/autoconfigure/validation/ValidationAutoConfiguration.class]: \n          Unsatisfied dependency expressed through method \'methodValidationPostProcessor\' parameter 0; \n          nested exception is \n            org.springframework.beans.factory.CannotLoadBeanClassException: \n              Error loading class [com.abc.bootbycustomloader.controller.UserController] \n              for bean with name \'userController\' defined in file \n                [D:\\code\\boot-by-custom-loader\\out\\production\\classes\\com\\abc\\bootbycustomloader\\controller\\UserController.class]: problem with class file or dependent class; \n                  nested exception is java.lang.LinkageError: loader (instance of  com/abc/bootbycustomloader/loader/MyClassLoader): \n                  attempted  duplicate class definition for name: \n                  "com/abc/bootbycustomloader/controller/UserController"\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n
@SpringBootApplication\npublic class ServerApplication {\n    public static void main(String[] args) {\n        MyResourceLoader rLoader = new MyResourceLoader();\n        SpringApplication app = new SpringApplicationBuilder().build();\n        app.addPrimarySources(Arrays.asList(ServerApplication.class));\n        app.setResourceLoader(rLoader);\n        app.run(args);\n    }\n}\n\n@RestController\n@RequestMapping("/user")\npublic class UserController {\n    @RequestMapping("/hello")\n    public String hello(){\n        System.out.println("hello hello hello...");\n        return "hello";\n    }\n}\n\npublic class MyResourceLoader extends DefaultResourceLoader {\n    private ClassLoader cl = new MyClassLoader();\n    @Override\n    public Resource getResource(String location) {\n        System.out.println("getResource: "+location);\n        return super.getResource(location);\n    }\n    @Override\n    public ClassLoader getClassLoader() {\n        return cl;\n    }\n}\n\npublic class MyClassLoader extends ClassLoader {\n    @Override\n    public Class<?> loadClass(String name) throws ClassNotFoundException {\n        if (name.equals("com.abc.bootbycustomloader.controller.UserController")) {\n            // assump that UserController is the encrypted class\n            // i need to load this encrypted class, and decrypted it!\n            System.out.println("!!!!!encrypted!!!!! : " + name);\n\n            // load the class from a special place, mock the decrypted processing\n            String path = "D:\\\\_clz\\\\UserController.class";\n            byte[] data = new byte[0];\n            try {\n                data = Files.readAllBytes(Paths.get(path));\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n            // mock decrypted processing success, return the decrypted class\n            Class<?> clz = defineClass(name, data, 0, data.length);  \n            return clz;\n        } else {\n            // assump that other class is not encrypted class\n            // just load it as usual\n            return super.loadClass(name);\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n