[위 에] URLClassLoader 를 사용 하여 외부 jar 패키지 의 자바 류 를 불 러 와 Class 파일 을 생 성 합 니 다.

12944 단어 자바ClassLoaderClass
먼저 인터넷 copy 의 말 솜 씨 를 보 여 주세요.
      //****************************
많은 경우 에 우리 가 쓴 자바 프로그램 은 모듈 로 나 뉘 어 져 있 습 니 다. 아주 좋 은 확장 메커니즘 이 있 습 니 다. 즉, 우 리 는 우리 자신의 자바 류 에 플러그 인 을 추가 하여 미래 에 우리 가 개발 할 수 있 는 종 류 를 실행 할 수 있 습 니 다. 아래 에 이러한 종 류 를 플러그 인 류 라 고 부 릅 니 다.
다음은 간단 한 실현 방법 이다.
Class A 는 프로그램의 주 입구 로 서 프로그램의 실행 입구 (main) 함 수 를 포함 합 니 다.그리고 main 함수 에서 외부 프로필 을 통 해 외부 프로필 을 통 해 플러그 인 류 의 정보 (어느 jar 패키지, jar 패키지 의 구체 적 인 경로 에 있 는 지) 를 얻 은 다음 jar 패키지 의 특정한 인 스 턴 스 를 얻어 해당 하 는 작업 을 수행 할 수 있 습 니 다.이 jar 가방 은 외부 jar 가방 일 가능성 이 높 습 니 다. 우리 가 직접 쓴 것 입 니 다. 그러면 우 리 는 어디 에 두 어야 그 가 스스로 찾 을 수 있 습 니까?구체 적 인 디 렉 터 리 를 class 에 넣 지 않 는 한 여러 번 시도 해 봤 습 니 다.path 에서 만 성공 적 으로 실행 할 수 있 습 니 다. 그렇지 않 으 면 이상 을 보고 하 는 것 은 하나의 Class NotFoundation Exception 일 뿐 종 류 를 찾 을 수 없습니다.하지만 이 jar 패 키 지 를 jar 패 키 지 를 실행 하 는 디 렉 터 리 에 압축 을 풀 면 classpath 의.. 해당 클래스 를 얻 을 수 있 습 니 다.하지만 이렇게 하면 프로 답지 못 해 보 입 니 다. 자바 가 쓴 것 은 모두 jar 가방 입 니 다. 자신 이 느끼 는 것 입 니 다.claspath 에 넣 으 면 새로운 jar 가방 을 쓸 때마다 설정 할 수 는 없 잖 아 요!
이렇게 해서 다음 과 같은 해결 방법 이 나 타 났 다.
해결 방법의 의 미 를 알 고 싶 으 면 먼저 자바 의 클래스 로드 체 제 를 알 아야 합 니 다.프로그램 이 실행 되 려 면 메모리 에 불 러 와 야 성공 적 으로 실 행 될 수 있다 는 것 은 잘 알려 져 있다.자바 프로그램 은 실행 가능 한 파일 이 아니 라 많은 독립 된 클래스 파일 로 이 루어 집 니 다.그래서 자바 에서 불 러 오 는 프로그램 은 클래스 를 하나의 외부 로 완성 합 니 다.이것 도 자바 의 class loader 로 딩 메커니즘 을 간단하게 알 아 봐 야 합 니 다.
자바 프로그램 이 실행 되 기 시 작 했 습 니 다. 첫 번 째 classloader 는 boottstrap classloader 입 니 다. 이 classloader 는 c + 언어 로 작성 되 었 습 니 다. 그 를 통 해 자바 의 핵심 클래스 를 불 러 옵 니 다.두 번 째 classloader 는 extension classloader 입 니 다. jre / lib 디 렉 터 리 의 ext 디 렉 터 리 에 있 는 jar 패 키 지 를 불 러 옵 니 다.그 다음 에 세 번 째 는 system classloader 이 고 응용 로 더 라 고도 불 리 며 주로 로 딩 - classpath 또는 시스템 의 전체 변수 인 ClassPath 의 클래스 를 완성 합 니 다.System.out.println(System.getProperty(“java.class.path”));classpath 설정 을 얻 을 수 있 습 니 다. 즉, system classloader 가 불 러 오 는 클래스 입 니 다. 네 번 째 classloader 는 사용자 정의 로 딩 클래스 일 수 있 습 니 다.일반적으로 하나의 종류의 로드 과정 은 현재 클래스 로 더 의 부모 로 더 를 통 해 찾 으 려 고 시도 합 니 다. 부모 로 더 를 찾 지 않 으 면 최종 boottstrap classloader 까지 불 러 오 려 고 시도 합 니 다. 찾 지 못 하면 위 에서 아래로 클래스 를 불 러 옵 니 다.이렇게 하 는 목적 은 사용자 정의 클래스 가 시스템 의 클래스 를 덮어 쓰 는 것 을 방지 하 는 것 입 니 다. 이러한 메커니즘 이 없 으 면 이런 농담 이 쉽게 발생 할 수 있 습 니 다. 자신 이 String 류 를 쓴 다음 에 new string 은 자신 이 쓴 String 류 입 니 다. 그러면 비교적 재 미 있 습 니 다.
//*********************************************
    다음은 제 가 최근 에 프로젝트 를 한 실제 코드 입 니 다. 참고 할 수 있 습 니 다.
1. URLClassLoader 대상 을 정의 하여 외부 jar 패 키 지 를 불 러 옵 니 다. jar 패 키 지 는 더 이상 jar 패키지 가 나타 나 지 않 습 니 다. 즉, 'class 파일 만 분석 합 니 다:
 private static void test1() {
  String path = "D:\\test.jar";//  jar    
  Set<Class<?>> classes = new LinkedHashSet<Class<?>>();//   Class  
  Map<Class<?>, Annotation[]> classAnnotationMap = new HashMap<Class<?>, Annotation[]>();//  Class        
  Map<Class<?>, Map<Method, Annotation[]>> classMethodAnnoMap = new HashMap<Class<?>, Map<Method,Annotation[]>>();//  Class             
  try {
   JarFile jarFile = new JarFile(new File(path));
   URL url = new URL("file:" + path);
   ClassLoader loader = new URLClassLoader(new URL[]{url});//     classLoader ,        load   ,       load  
   Enumeration<JarEntry> es = jarFile.entries();
   while (es.hasMoreElements()) {
    JarEntry jarEntry = (JarEntry) es.nextElement();
    String name = jarEntry.getName();
    if(name != null && name.endsWith(".class")){//    .class  ,       jar 
     //                ,    jar    
    	//Class<?> c = Thread.currentThread().getContextClassLoader().loadClass(name.replace("/", ".").substring(0,name.length() - 6));
     Class<?> c = loader.loadClass(name.replace("/", ".").substring(0,name.length() - 6));//     loader      
     System.out.println(c);
     classes.add(c);
     Annotation[] classAnnos = c.getDeclaredAnnotations();
     classAnnotationMap.put(c, classAnnos);
     Method[] classMethods = c.getDeclaredMethods();
     Map<Method, Annotation[]> methodAnnoMap = new HashMap<Method, Annotation[]>();
     for(int i = 0;i<classMethods.length;i++){
      Annotation[] a = classMethods[i].getDeclaredAnnotations();
      methodAnnoMap.put(classMethods[i], a);
     }
     classMethodAnnoMap.put(c, methodAnnoMap);
    }
   }
   System.out.println(classes.size());
  } catch (IOException e) {
   e.printStackTrace();
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
  }
 }


이상 의 경우 다른 procject 프로젝트 에 test 방법 을 쓸 수 있 습 니 다. 평소에 가장 많이 사용 되 는 것 입 니 다. class 파일 에 다른 jar 가방 에 의존 하 는 대상 이 있 을 때 이 jar 가방 을 이 테스트 방법 을 쓰 는 procject 와 buildPath 로 복사 해 야 합 니 다. 그렇지 않 으 면 실 행 될 때 Class 대상 의 이상 을 찾 을 수 없습니다.
2. 두 번 째 상황 은 jar 가방 에 있 는 jar 가방 을 불 러 오 는 Class 대상 과 특정한 properties 파일 을 읽 는 방법 입 니 다.
private static void test2() {
  String path = "D:\\test.jar";// jar      jar 
  try {
   JarFile jarfile = new JarFile(new File(path));
   Enumeration<JarEntry> es = jarfile.entries();
   while (es.hasMoreElements()) {
    JarEntry je = es.nextElement();
    String name = je.getName();
    if(name.endsWith(".jar")){//  jar   jar 
     File f = new File(name);
     JarFile j = new JarFile(f);
     Enumeration<JarEntry> e = j.entries();
     while (e.hasMoreElements()) {
      JarEntry jarEntry = (JarEntry) e.nextElement();
      System.out.println(jarEntry.getName());
      //.........           
     }
    }
//    System.out.println(je.getName());
    if(je.getName().equals("entity_pk.properties")){
     InputStream inputStream = jarfile.getInputStream(je);
     Properties properties = new Properties();
     properties.load(inputStream);
     Iterator<Object> ite = properties.keySet().iterator();
     while (ite.hasNext()) {
      Object key = ite.next();
      System.out.println(key + " : " +properties.get(key));
     }
    }
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
 }

3. 세 번 째 상황 은 이 항목 에서 가방 의 Class 대상 을 가 져 오 는 것 입 니 다. 물론 테스트 방법 은 이 항목 에 적 혀 있 습 니 다. (이렇게 하면 classLoader 는 대상 을 직접 알 수 있 습 니 다. URLClassLoader 를 사용자 정의 할 필요 가 없습니다. Thread. current Thread (). getContextClassLoader (). loadclass (...)Class 대상 을 직접 얻 을 수 있 습 니 다. ClassPath 에서 찾 아 보 세 요. System. out. print (System. getProperty ("java. class. path") 에서 classPath 경 로 를 찾 을 수 있 습 니 다.
private static Set<Class<?>>  getclass() {
  Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
  boolean flag = true;//      
 
  String packName = "com.yk.framework.db";
//  String packName = "org.jdom";
  String packDir = packName.replace(".", "/");
  Enumeration<URL> dir;
  try {
   dir = Thread.currentThread().getContextClassLoader().getResources(packDir);
   while(dir.hasMoreElements()){
    URL url = dir.nextElement();
    System.out.println("url:***" + url);
    String protocol = url.getProtocol();//     
    if("file".equals(protocol)){
     System.err.println("file     ");
     String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
     System.out.println("filePath :" + filePath);
     findAndAddClassesInPackageByFile(packName, filePath,flag,classes);
    }else if("jar".equals(protocol)){
     System.err.println("jar    ");
     JarFile jar;
     jar = ((JarURLConnection)url.openConnection()).getJarFile();
     Enumeration<JarEntry> entries = jar.entries();
     while(entries.hasMoreElements()){
      JarEntry entry = entries.nextElement();
      String name = entry.getName();
      System.out.println(">>>>:" + name);
      //......
     }
     
    }
    
   }
   
  } catch (IOException e) {
   e.printStackTrace();
  }
  System.out.println(classes.size());
  return classes;
  
 }
 

아래 위의 두 번 째 코드
 private static void findAndAddClassesInPackageByFile(String packName, String filePath, final boolean flag, Set<Class<?>> classes) {
  File dir = new File(filePath);
  if( !dir.exists() || !dir.isDirectory()){
   System.out.println("        ");
   return;
  }
  File[] dirfiles = dir.listFiles(new FileFilter(){
   @Override
   public boolean accept(File pathname) {
    return flag && pathname.isDirectory() || pathname.getName().endsWith(".class");
   }
  });
  for (File file : dirfiles) {
   if(file.isDirectory()){//     ,    
    findAndAddClassesInPackageByFile(packName + "." + file.getName(),file.getAbsolutePath(),flag,classes);
   }else{//     
    String className = file.getName().substring(0,file.getName().length() - 6);
    System.out.println("  :" +className);
    try {
     classes.add(Thread.currentThread().getContextClassLoader().loadClass(packName + "." + className));
    } catch (ClassNotFoundException e) {
     e.printStackTrace();
    }
   }
  }
 }

자, 대체로 그렇습니다. 열심히 공부 하고 매일 향상 하 세 요!하하 ~ ~
보충:
4. jar 패키지 의 enity 읽 기pk. properties 키 값 이 프로젝트 로 컬 enitypk. properties 파일 중
	/**
	 *   jar   entity_pk.properties        entity_pk.properties   
	 */
	private static void test2() {
		String path = "D:\\test.jar";
		try {
			JarFile jarFile = new JarFile(new File(path));
			Enumeration<JarEntry> es = jarFile.entries();
			while (es.hasMoreElements()) {
				JarEntry jarEntry = (JarEntry) es.nextElement();
				String name = jarEntry.getName();
				if(name.equals("entity_pk.properties")){
					InputStream inputStream = new FileInputStream(name);
					Properties prop = new Properties();
					prop.load(inputStream);// load   entity_pk.propertoes  
					InputStream inputStream2 = jarFile.getInputStream(jarEntry);//  jar entity_pk.propertoes   
					Properties prop2 = new Properties();
					prop2.load(inputStream2);
					Enumeration<Object> ks = prop2.keys();
					OutputStream out = new FileOutputStream(name);
					while (ks.hasMoreElements()) {
						String key =  (String)ks.nextElement();
						System.out.println(key + " : " +prop2.getProperty(key));
						prop.setProperty(key, prop2.getProperty(key));// jar entity_pk.properties       
					}
					prop.store(out,"");
				}
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

 5. 읽 기와 쓰기 dbconfig. xml 파일
	/**
	 *   db_config.xml  
	 */
	private static void test3() {
		String path = "D:\\test.jar";
		try {
			JarFile jarFile = new JarFile(new File(path));
			Enumeration<JarEntry> es = jarFile.entries();
			while (es.hasMoreElements()) {
				JarEntry jarEntry = (JarEntry) es.nextElement();
				String name = jarEntry.getName();
				if(name.equals("db_config.xml")){
					InputStream inputStream = jarFile.getInputStream(jarEntry);
					SAXBuilder builder = new SAXBuilder();
					Document doc = null;
					try {
						doc = builder.build(inputStream);
						if(doc != null){
							Element e = doc.getRootElement();
							Element proxool = e.getChild("proxool");
							List<Element> children = proxool.getChildren();
							for (Element element : children) {
								System.out.println(element.getText());
							}
							Element s = new Element("test");
							s.addContent("test");
							proxool.addContent(s);
							XMLOutputter outputter = new XMLOutputter();
							outputter.output(doc, new FileOutputStream("config/db_config.xml"));
						}
					} catch (JDOMException e) {
						e.printStackTrace();
					}finally{
						if(inputStream != null){
							inputStream.close();
						}
					}
					
				}
				
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

좋은 웹페이지 즐겨찾기