How Java scans all classes under the specified package

Source: Internet
Author: User

In writing an MVC framework, you need to scan the components from the package and register them with the container, and the JDK does not provide the out-of-the-box methods that can be implemented by itself.

Function:
Given a package name, it is programmed to get all the class files under the package (and all its child packages). For example, enter the package name com.myapp.util , output the fully qualified name of the class under the package com.myapp.util.StringUtils , and com.app.util.ImageUtils so on.

Ideas:
Some Web servers unzip the jar package while the deployment is running, so the class file is in the normal file directory. If the Web server does not press the JAR package, the class file is directly present in the jar package. For the former, simply navigate to the directory where the class file is located, then read the class file name, and for the latter, you need to locate the directory where the jar package is located and then use JarInputStream the Read jar package to get the class name.

Realize:
This is copied from the written project code directly, if you want to run this code, you need to change all the Logger.debugSystem.out.println()

/** * This scanner are used to find out all classes in a package. * Created by WHF on 15-2-26. * / Public  class Classpathpackagescanner implements Packagescanner {    PrivateLogger Logger = Loggerfactory.getlogger (Classpathpackagescanner.class);PrivateString Basepackage;PrivateClassLoader cl;/** * Construct An instance and specify the base package it should scan.     * @param basepackage The base package to scan. */     Public Classpathpackagescanner(String basepackage) { This. basepackage = Basepackage; This. CL = GetClass (). getClassLoader (); }/** * Construct An instance with the base package and class loader.     * @param basepackage The base package to scan.     * @param CL Use this class load to locate the package. */     Public Classpathpackagescanner(String Basepackage, ClassLoader cl) { This. basepackage = Basepackage; This. CL = CL; }/** * Get All fully qualified names located on the specified package * and its sub-package.     * * @return A List of fully qualified names. * @throws ioexception * *    @Override     PublicList<string>getfullyqualifiedclassnamelist()throwsIOException {Logger.info ("Start scanning all classes under package {}", basepackage);returnDoscan (Basepackage,NewArraylist<> ()); }/** * Actually perform the scanning procedure.     * * @param basepackage * @param namelist A list to contain the result.     * @return A List of fully qualified names. * * @throws ioexception * *    PrivateList<string>Doscan(String basepackage, list<string> namelist)throwsIOException {//Replace dots with splashesString Splashpath = Stringutil.dottosplash (basepackage);//Get file pathURL url = cl.getresource (Splashpath); String FilePath = Stringutil.getrootpath (URL);//Get classes in the.        //If The Web server unzips the jar file, then the classes would exist in the form of        //Normal file in the directory.        //If The Web server does not unzip the jar file and then classes'll exist in jar file.list<string> names =NULL;//contains the name of the class file. E.g, apple.class'll be stored as "Apple"        if(Isjarfile (FilePath)) {//Jar file            if(Logger.isdebugenabled ()) {Logger.debug ("{} is a jar package", FilePath);        } names = Readfromjarfile (FilePath, Splashpath); }Else{//Directory            if(Logger.isdebugenabled ()) {Logger.debug ("{} is a directory", FilePath);        } names = Readfromdirectory (FilePath); } for(String name:names) {if(Isclassfile (name)) {//namelist.add (Basepackage + "." + stringutil.trimextension (name));Namelist.add (Tofullyqualifiedname (name, basepackage)); }Else{//This is a directory                //Check this directory for more classes                //Do recursive invocationDoscan (Basepackage +"."+ Name, namelist); }        }if(Logger.isdebugenabled ()) { for(String n:namelist) {Logger.debug ("Find {}", n); }        }returnNameList; }/** * Convert Short class name to fully qualified name. * e.g., String-java.lang.String * /    PrivateStringTofullyqualifiedname(String shortname, String basepackage) {StringBuilder SB =NewStringBuilder (Basepackage); Sb.append ('. '); Sb.append (Stringutil.trimextension (shortname));returnSb.tostring (); }PrivateList<string>Readfromjarfile(String jarpath, String splashedpackagename)throwsIOException {if(Logger.isdebugenabled ()) {Logger.debug ("read class from Jar package: {}", Jarpath); } Jarinputstream Jarin =NewJarinputstream (NewFileInputStream (Jarpath));        Jarentry entry = Jarin.getnextjarentry (); list<string> NameList =NewArraylist<> (); while(NULL! = Entry) {String name = Entry.getname ();if(Name.startswith (Splashedpackagename) && isclassfile (name))            {Namelist.add (name);        } entry = Jarin.getnextjarentry (); }returnNameList; }PrivateList<string>readfromdirectory(String Path) {File File =NewFile (path); string[] names = File.list ();if(NULL= = names) {return NULL; }returnArrays.aslist (names); }Private Boolean Isclassfile(String name) {returnName.endswith (". Class"); }Private Boolean Isjarfile(String name) {returnName.endswith (". Jar"); }/** * for test purpose. */     Public Static void Main(string[] args)throwsException {Packagescanner scan =NewClasspathpackagescanner ("Cn.fh.lightning.bean");    Scan.getfullyqualifiedclassnamelist (); }}

The above code uses the StringUtils class, as follows:

 Public  class stringutil {    Private Stringutil() {    }/** * "FILE:/HOME/WHF/CN/FH", "/home/whf/cn/fh" * "JAR:FILE:/HOME/WHF/FOO.JAR!CN/FH", "/HOME/WHF/FO" O.jar "* *     Public StaticStringGetrootpath(URL URL) {String FILEURL = Url.getfile ();intpos = Fileurl.indexof ('! ');if(-1= = pos) {returnFILEURL; }returnFileurl.substring (5, POS); }/** * "cn.fh.lightning", "cn/fh/lightning" * @param name * @return  * *     Public StaticStringDottosplash(String name) {returnName.replaceall ("\\.","/"); }/** * "Apple.class", "Apple" * *     Public StaticStringtrimextension(String name) {intpos = Name.indexof ('. ');if(-1! = pos) {returnName.substring (0, POS); }returnName }/** */application/home/home * @param uri * @return  */     Public StaticStringTrimuri(String URI) {String trimmed = uri.substring (1);intSplashindex = Trimmed.indexof ('/');returnTrimmed.substring (Splashindex); }}

Execution Result:

How Java scans all classes under the specified package

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.