如何为RunTime动态添加自定义classpath

参考:https://ted0928.iteye.com/blog/543599

 

这几天在做一个小项目的时候 有这样一个需求, 程序需要动态引入一个.class文件,然后用Class.forName(name)将其载入,从而得到.class文件的信息.如果是在系统当前指定的classpath下,可以直接载入,但是若是自定义的路径下的.class文件,就会报找不到类文件的错.后来我问了老师,老师提供的方法是用ClassLoader.defineClass(byte[] b, int off, int len)来载入.class文件,这种方法已经成功.但我在想,怎么能将这个文件的路径加入classpath中呢,开始我想到了System.setProperty(String key, String value)这个方法,但后来证明是错的,这种方式是对classpath不起作用的,因为系统的类加载器在启动期间很早的时候就读取classpath了,系统在后来是不再读取classpath的,所以修改对系统没有任何作用.这几天在google看到一篇文章,这位国外的仁兄用了一种方法,可以实现动态添加自定义classpath,很好的程序,转载来学习一下. 

 

import java.lang.reflect.InvocationTargetException;  
import java.lang.reflect.Method;                     
  
import java.io.File;  
import java.io.IOException;  
  
import java.net.URL;  
import java.net.URLClassLoader;  
  
/** 
 * Allows programs to modify the classpath during runtime.               
 */                                                                       
public class ClassPathUpdater {                                           
  /** Used to find the method signature. */                               
  private static final Class[] PARAMETERS = new Class[]{ URL.class };     
  
  /** Class containing the private addURL method. */  
  private static final Class> CLASS_LOADER = URLClassLoader.class;  
  
  /** 
   * Adds a new path to the classloader. If the given string points to a file, 
   * then that file's parent file (i.e., directory) is used as the 
   * directory to add to the classpath. If the given string represents a 
   * directory, then the directory is directly added to the classpath. 
   * 
   * @param s The directory to add to the classpath (or a file, which 
   * will relegate to its directory). 
   */  
  public static void add( String s )  
    throws IOException, NoSuchMethodException, IllegalAccessException,  
           InvocationTargetException {  
    add( new File( s ) ); :evil:   
  }  
  
  /** 
   * Adds a new path to the classloader. If the given file object is 
   * a file, then its parent file (i.e., directory) is used as the directory 
   * to add to the classpath. If the given string represents a directory, 
   * then the directory it represents is added. 
   * 
   * @param f The directory (or enclosing directory if a file) to add to the 
   * classpath. 
   */  
  public static void add( File f )  
    throws IOException, NoSuchMethodException, IllegalAccessException,  
           InvocationTargetException {  
    f = f.isDirectory() ? f : f.getParentFile();  
    add( f.toURI().toURL() );  
  }  
  
  /** 
   * Adds a new path to the classloader. The class must point to a directory, 
   * not a file. 
   * 
   * @param url The path to include when searching the classpath. 
   */  
  public static void add( URL url )  
    throws IOException, NoSuchMethodException, IllegalAccessException,  
           InvocationTargetException {  
    Method method = CLASS_LOADER.getDeclaredMethod("addURL", PARAMETERS );  
    method.setAccessible( true );  
    method.invoke( getClassLoader(), new Object[]{ url } );  
  }  
  
  private static URLClassLoader getClassLoader() {  
    return (URLClassLoader)ClassLoader.getSystemClassLoader();  
  }  
}  
   

Example Usage 

The following example will add /home/user/dev/java/app/build/com/package to the classpath at runtime: 

try {  
  ClassPathUpdater.add(/home/user/dev/java/app/build/com/package/Filename.class);  
}  
catch( Exception e ) {  
  e.printStackTrace();  
}  

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是CXF结合Spring Boot利用自定义注解动态发布RS接口的一个例子: 首先,我们需要定义一个自定义注解,例如@WebService。这个注解可以包含一些元数据,例如服务名称、服务端口等等。我们可以按照以下方式定义这个注解: ```java @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented public @interface WebService { String name(); int port() default 8080; } ``` 然后,我们需要定义一个类,用于获取注解信息并发布服务。在这个类中,我们可以使用CXF提供的API来创建服务和端口,并将它们发布到网络上。我们可以按照以下方式定义这个类: ```java @Component public class ServicePublisher implements ApplicationListener<ContextRefreshedEvent> { @Autowired private ApplicationContext context; @Override public void onApplicationEvent(ContextRefreshedEvent event) { Map<String, Object> beans = context.getBeansWithAnnotation(WebService.class); for (Object bean : beans.values()) { JaxRsServerFactoryBean factory = new JaxRsServerFactoryBean(); factory.setServiceBean(bean); WebService webService = bean.getClass().getAnnotation(WebService.class); factory.setAddress("http://localhost:" + webService.port() + "/" + webService.name()); Server server = factory.create(); server.start(); } } } ``` 在这个类中,我们使用ApplicationContext来获取所有带有@WebService注解的Bean,并使用JaxRsServerFactoryBean来创建服务和端口。然后,我们将服务和端口发布到网络上。 接下来,在Spring Boot应用程序中,我们可以使用@Bean注解来创建一个实例化我们刚才定义的类的Bean。我们可以按照以下方式定义这个Bean: ```java @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean public ServicePublisher servicePublisher() { return new ServicePublisher(); } } ``` 在这个Bean中,我们创建了一个ServicePublisher实例。 然后,我们需要使用@Import注解将CXF的配置文件导入到Spring Boot应用程序中。我们可以按照以下方式定义这个注解: ```java @Configuration @ImportResource({ "classpath:META-INF/cxf/cxf.xml", "classpath:META-INF/cxf/cxf-servlet.xml" }) public class CXFConfig { } ``` 在这个注解中,我们将CXF的配置文件导入到Spring Boot应用程序中。 最后,我们可以使用Spring Boot的自动配置功能来自动配置CXF和我们的自定义注解,以便我们可以轻松地发布服务。我们只需要在我们的自定义注解上添加@javax.ws.rs.Path注解即可。例如: ```java @WebService(name = "hello", port = 8080) @Path("/hello") public class HelloResource { @GET @Produces(MediaType.TEXT_PLAIN) public String sayHello() { return "Hello, world!"; } } ``` 在这个例子中,我们将我们的自定义注解@WebService和@Path注解添加到HelloResource类上,以便我们可以将它作为RS接口发布。 这就是CXF结合Spring Boot利用自定义注解动态发布RS接口的一个例子。希望这可以帮助你。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值