There are a number of scenarios in which a package scan is needed in a project, typically when the project is initialized, and the classes under a certain packages are treated with special care. The function that I want to implement now is to scan the specified package path when a filter or interceptor is initialized, traverse each of the following classes, find out all the methods that use a special annotation on method, and then cache it, when the methods interceptor works , there is no need to judge whether the method needs to be intercepted.
There are many examples of your own code to implement the scan package, but if you have tools that have been implemented for you and have undergone universal validation, it is not necessary to build your own wheels.
Class Classpathbeandefinitionscanner with scan packages in spring frame the Findcandidatecomponents method is the basis for our transformation.
/** * scan the class path for candidate components. * @param basepackage the package to check for annotated classes * @ Return a corresponding set of autodetected bean definitions */public set<beandefinition> findcandidatecomponents (string basepackage) { Set<beandefinition> candidates = new linkedhashset<beandefinition> (); try { String packageSearchPath = resourcepatternresolver.classpath_all_url_prefix + resolvebasepackage (basepackage) + "/" + this.resourcePattern; resource[] resources = this.resourcepatternresolver.getresources ( Packagesearchpath); &Nbsp; boolean traceenabled = logger.istraceenabled (); boolean debugenabled = logger.isdebugenabled (); for (resource resource : resources) { if (traceenabled) { Logger.trace ("scanning " + resource); } if (Resource.isreadable ()) { try { MetadataReader metadataReader = This.metadataReaderFactory.getMetadataReader (Resource); if (Iscandidatecomponent (metadatareader)) { scannedgenericbeandefinition sbd = new scannedgenericbeandefinition (Metadatareader); sbd.setresource (Resource); sbd.setsource (Resource); if (Iscandidatecomponent (SBD)) { if (debugenabled) { logger.debug ("Identified candidate component class: " + resource); } candidates.add (SBD); } else { if (debugenabled) { logger.debug ("ignored because not a concrete top-level class: " + resource); } } } else { if ( traceenabled) { logger.trace ("ignored because not matching any filter: " + resource); } } } catch (Throwable ex) { throw new beandefinitionstoreexception ( "failed to read candidate component class: " + resource, &NBSP;EX); } } else { if (traceenabled) { logger.trace ("Ignored because not readable: "&NBsp;+ resource); } } } } catch (Ioexception ex) { throw new Beandefinitionstoreexception ("i/o failure during classpath scanning", ex); } return candidates;}
The transformation is as follows:
The loadcheckclassmethods of the method is a comma-delimited package path, such as com.xx
Using Spring's
Resourcepatternresolver to find the resources under the package resource, because our scan pattern is a. class file, so here's resource is the class file protected static final String Default_resource_pattern = "**/*.class";
/** * */private void loadcheckclassmethods (String) depending on the configuration * load of the scan package that needs to be checked scanpackages) { string[] scanpackagearr = scanpackages.split ( ","); resourcepatternresolver resourcepatternresolver = new Pathmatchingresourcepatternresolver (); metadatareaderfactory metadatareaderfactory = new cachingmetadatareaderfactory (resourcepatternresolver); for ( String basepackage : scanpackagearr) { if (Stringutils.isblank (basepackage)) { continue; } string packagesearchpath = resourcepatternresolver.classpath_all_url_prefix + &nBsp; classutils.convertclassnametoresourcepath ( Systempropertyutils.resolveplaceholders (basepackage) + "/" + DEFAULT_RESOURCE_PATTERN; try { resource[] resources = resourcepatternresolver.getresources ( Packagesearchpath); for (Resource resource : resources) { //Check resource, the resource here are class loadclassmethod (Metadatareaderfactory, resource); } } catch (EXCEPTION&NBsp;e) { log.error (" Initialize Sensitivewordinterceptor failed ", e); } }}
/** * loading resources, judging the methods inside * * @param metadataReaderFactory Tools for reading resource as class in spring * @param resource The resources here is a class * @throws IOException */private Void loadclassmethod (Metadatareaderfactory metadatareaderfactory, resource resource) throws ioexception { try { if (Resource.isreadable ()) { metadatareader metadatareader = metadatareaderfactory.getmetadatareader (Resource); if (Metadatareader != null) { string classname = metadatareader.gEtclassmetadata (). GetClassName (); try { trycachemethod (ClassName); } catch (Classnotfoundexception e) { log.error ("Check" + className + "do not contain required information failed", e); } } } } catch (exception e) { log.error (" The method implementation in the judgment class needs to detect XXX failure ", e); }}
/** * all the method below the action to see if they need to verify the XXX * , if necessary, into the cache * * @param fullclassname */private void trycachemethod (String fullclassname) throws Classnotfoundexception { class<?> clz = class.forname ( FullClassName); method[] methods = clz.getdeclaredmethods (); for (method method : methods) { if (Method.getmodifiers () != modifier.public) { continue; } if (CheckXXX.class.isAssignableFrom (check_annotation)) { CheckXXX checkXXX = (checkxxx ) method.getannotation (Check_annotation); if (CheckXXX != null && checkxxx.check ()) { cache.put (fullclassname + ".") + method.getname (), checkxxx); log.info ("A method to check for XXX is detected:" + fullClassName + ".") + method.getname ()); } } }}
What Trycachemethod do is cache the public method that needs to be handled.
Tested, this way can be taken to the Web class file and jar package in the class file
Use spring to implement class scanning under the package