title: how to use custom custom classloader in springboot
body: <p><strong>How to load beans using custom classloader in spring boot</strong></p>
  
  <p>i need to encrypted the spring boot project.</p>
  
  <p>at first i try using <strong>proguard</strong>, but fail because spring use lots of Annotations and it has <em>DI</em> .</p>
  
  <p>then i try using <strong>custom classloader</strong>. i want to encrypt my class files first, and then use my custom classloader to load the encryped class file, then decrypted it。</p>
  
  <p>here it is my demo: <a href="https://github.com/CaiBaoHong/boot-by-custom-loader" rel="noreferrer">https://github.com/CaiBaoHong/boot-by-custom-loader</a></p>
  
  <p>when it is starting up it fail:</p>
  
  <pre><code>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"
  </code></pre>
  
  <hr>
  
  <pre><code>@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&lt;?&gt; 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&lt;?&gt; 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);
          }
      }
  }
  </code></pre>