La reflexión de Java mencionada esta vez implica mucho código. Debido a que la reflexión se usa a menudo en el trabajo, hemos realizado muchas abstracciones y filtros al código. Aunque el código es grande, es simple y fácil de usar, y los complementos de filtro también son fáciles de modificar.
La siguiente es una descripción de dónde es más fácil usar la reflexión en el trabajo. Por ejemplo, los complementos o filtros, si hay menos subclases abstractos, configurarlas en XML y otras estructuras también pueden lograr el mismo efecto. Si desea ser más flexible, puede usarlo directamente después de agregar complementos o subclases de código de filtro. Puede ser mejor reflexionar, y todas las subclases hereditarias se obtienen escaneando todos los archivos de clase o JAR. Si escanea todos los archivos cada llamada, afectará el rendimiento. Por lo tanto, se agrega un caché de reflexión a la implementación para almacenar en caché todos los resultados de reflexión como una clave para todos los parámetros involucrados en la obtención de la subclase de reflexión. Si es la misma clave la próxima vez, no se volverá a repetir.
El ejemplo del código es el siguiente:
public static void main (string [] args) {// Establezca el rango de escaneo, que puede ser la ubicación del archivo de clase, como la ubicación en bin, o el comienzo de mysql o el final de mysql, // establecer "" para escanear todo, esto es consumo de tiempo, reflejils.CreateCharedReflecciones ("classes", "bin", "mysql");; "); Pruebe {// Puede establecer escaneos completos cada vez en la etapa de depuración // beans.setDesigntime (true); Colección final <String> Subtypes = ReflectUtils.listsubClass (ia.class); // para (String final Subtype: SubtyPes) {// Lo que obtienes aquí son System.out.println (subtype); final ia impl = reflectUtils.initClass (subtipo, ia.class); if (null == impl) continuar; // a través de este método, puede realizar operaciones de manera unificada, Impl.print (); }} catch (Exception e) {E.PrintStackTrace (); }}Resultado de la ejecución del código:
// Alcane el archivo para evitar volver a repite cada vez que se llama a la reflexión // si elimina el archivo, se rescatará cuando se vuelva a llamar a la reflexión. En general, el archivo se eliminará cuando haya subclases en el código. Xmlutils.readxml falla: ./ configuration.ref (el sistema no puede encontrar el archivo especificado.) Net.simple.reflect.test.bnet.simple.reflect.test.bnet.simple.reflect.test.bnet.simple.reflect.test.dnet.simple.reflect.test.vlv
Para más detalles, consulte el código fuente. Aquí hay dos códigos de clases principales. Dirección del código fuente: https://git.oschina.net/eliyanfei/api_tools
paquete net.simple.reflect; import java.io.file; import java.io.ioexception; import java.net.jarurlconnection; import java.net.url; import java.net.urlDecoder; import java.util.arraylist; import java.util.collection; import java.util.enumeral; importación; java.util.linkedhashmap; import java.util.list; import java.util.map; import java.util.concurrent.timeunit; import java.util.jar.jarEntry; import java.util.jar.jarfile; import java.util.zip.zipentry; import net.simple.reflect.filter.ipathurlfilter; import net.simple.reflect.filter.isubTypeFilter; import net.simple.reflect.filter.ityPeFilter; import oanfei [email protected] * 2 de noviembre de 2016 a las 3:23:49 PM * */Public Final Class Reflections {Colección final privada <URL> Pathurls; Colección final privada <PathurlFilter> PathurlFilters; COLECCIÓN FINAL PRIVADA <TypeFilter> Tyefilters; Subtypefilter privado isubtypefilter; Public Reflections () {typeFilters = new ArrayList <TiPeFilter> (); pathUrlFilters = new ArrayList <PathurlFilter> (); this.pathurls = classpathHelper.getUrlsforcurrentClassPath (); } Reflexiones públicas (colección final <url> pathurls) {this.pathurls = pathUrls; typeFilters = new ArrayList <TiPeFilter> (); pathUrlFilters = new ArrayList <PathurlFilter> (); } / ** * @param subtypeFilter * El subtypeFilter para establecer * / public void setSubTypeFilter (ISUBTyPeFilter final subtypefilter) {this.subTypeFilter = subtypeFilter; } / ** * @return the subtypeFilter * / public isubTypeFilter getSubTypeFilter () {return subtypeFilter; } Reflexiones públicas addPathUrlFilter (final ipathurlfilter pathurlFilter) {if (null == pathurlFilter) devuelve esto; if (! this.pathurlfilters.contains (pathurlfilter)) this.pathurlFilters.add (pathUrlFilter); devolver esto; } Public Reflections AddTypeFilter (TypeFilter TypeFilter final) {if (null == typeFilter) Devuelve esto; if (! this.typeFilters.contains (typeFilter)) this.typeFilters.add (typeFilter); devolver esto; } cadena final estática privada histfile = "./configuration.ref"; Histomio de documentos privados; Public Collection <String> getSubTypeSfast (clase final <?> basetype) {//, cadena final ... typenames // primero filtra la ruta actualmente se permite escanear StringBuilder final bufpathsid = new StringBuilder (32); mapa final <archivo, url> fileUrls = new LinkedHashMap <archivo, url> (8); para (URL final Pathurl: Pathurls) {if (! AcceptPathUrl (pathurl)) continuar; Archivo archivo = null; Pruebe {archivo = nuevo archivo (urlDecoder.decode (pathurl.getFile (), "utf-8")); } Catch (Excepción final e) {archivo = nuevo archivo (pathurl.getFile ()); } fileurls.put (archivo, pathurl); if (! file.exists ()) // es el archivo URL? Ignorar continuar; bufpathsid.append (file.getName ()). append (file.lastModified ()); } Final String Domid = Md5.GethashString (bufpathsid.ToString ()); if (null == histom) HISDIM = w3cutils.readxml (histfile); if (null == histom) HISDIM = w3cutils.news.news ("r"); Elemento rootele = histom.getDocumentElement (); if (null == rootele) histom.appendChild (rootele = histom.createElement ("r")); if (! Domid.equals (rootele.getAttribute ("id"))) {rootele.getParentNode (). removeChild (rootele); histom.appendChild (rootele = histom.createElement ("r")); rootele.setAttribute ("id", domid); } cadena final basetypeId = md5.gethashString (basetype.getName ()); Elemento refele = w3cutils.firstchildelement (rootele, "e", "id", basetypeId); if (null! = refele) {Lista final <emente> ValueAles = w3cutils.childelementList (refele, "f"); colección final <string> result = new ArrayList <String> (valueeles.size ()); for (el elemento final valueele: valueAles) {result.Add (new String (base64.DecodeFast (valueEle.getAttribute ("id"))); } resultado de retorno; } final Threadpool <ListSubTypes> Pool = new Threadpool <ListSubTypes> (); para (Final File FileKey: FileUrls.KeySet ()) {Pool.execute (new ListSubTypes (Basetype, FileKey, FileUrls.get (FileKey))); } try {Pool.shutdown (3, TimeUnit.Minutes); } Catch (final InterruptedException e) {E.PrintStackTrace (); // para la depuración} Collection final <String> result = new ArrayList <String> (); para (tarea final de listsubtypes: piscal.getThreadRunables ()) {result.addall (task.Result); } refele = w3cutils.addele (rootele, "e"); refele.SetAttribute ("id", basetypeId); for (String final itm: resultado) {w3cutils.addele (refele, "f"). setAttribute ("id", base64.EncodeToString (itm.getBytes (), falso)); } try {w3cutils.writexmlDocument (histfile, histom); } Catch (Excepción final e) {} Resultado de retorno; } / ** * @see {@link reflectutils#createSharedReflections (string ...)} * @see {@link reflectutils#setSharedReflections (reflexions)} * @see {@link reflectUtils#listsubclass (class)} * @param basetype * @return * / public collection <String> getSubtypes (final class <? typenames) {// Final Threadpool <ListSubTypes> Pool = new ThreadPool <ListSubTypes> (); para (URL final Pathurl: Pathurls) {if (! AcceptPathUrl (pathurl)) continuar; Archivo archivo = null; Pruebe {archivo = nuevo archivo (urlDecoder.decode (pathurl.getFile (), "utf-8")); } Catch (Excepción final e) {archivo = nuevo archivo (pathurl.getFile ()); } piscir.execute (nuevo listsubtypes (basetype, archivo, pathurl, typenames)); } try {Pool.shutdown (3, TimeUnit.Minutes); } Catch (final InterruptedException e) {E.PrintStackTrace (); // para la depuración} Collection final <String> result = new ArrayList <String> (); para (tarea final de listsubtypes: piscal.getThreadRunables ()) {result.addall (task.Result); } resultado de retorno; } class ListSubTyPes implementa Runnable {archivo final del archivo; Clase final <?> Basetype; Pathurl de URL final; cadena final [] typenames; Public ListSubTypes (final de clase <?> Basetype, archivo final, archivo final, URL final pathurl, cadena final ... typenames) {this.basetype = basetype; this.file = file; this.pathurl = pathurl; this.typenames = typenames; } Colección <string> resultado = new ArrayList <String> (4); @Override public void run () {if (file.isDirectory ()) {listSubTypesFromDirectory (archivo, basetype, pathUrl, file, resultado, typenames); } else listSubTyPesFromjar (basetype, pathUrl, resultado, typenames); }} / ** * @param basetype * @param pathurl * @param resultado * / public void listSubtypeSFromDirectory (Final File Basedirectory, clase final <?> BaseType, final de url final, directorio final de archivos, colección final <string> resultado, cadena final ... typenames) {archivos = archivos = directory.listfiles (););; if (null == archivos) archivos = nuevo archivo [] {}; Cadena Clazzpath; Final int baseLen = Basedirectory.getAbSolutePath (). Longitud () + 1; para (archivo final del archivo: archivos) {if (file.isDirectory ()) {listSubTypeSFromDirectory (Basedirectory, Basetype, Pathurl, File, Result, Typenames); } else {clazzPath = file.getAbSolutePath (). Substring (BaseLen); ClazzPath = ClazzPath.replace ('//', '/'); dotypesfilter (basetype, pathurl, resultado, clazzpath, typenames); }}} / ** * @param basetype * @param pathurl * @param resultado * / public void listSubtypeSFromjar (final class <?> basetype, url pathurl, colección final <string> resultado, resultado final ... string ... Jarfile jarfile = null; Pruebe {if ("file" .equals (pathurl.getProtocol ())) pathUrl = new url ("jar:" + pathUrl.toexternalform () + "!/"); jarfile = ((jarurlconnection) pathurl.openconnection ()). getJarfile (); } Catch (Excepción final e) {String final filePath = pathUrl.getFile (); // si está en la plataforma WIN if (filePath.IndexOf (':')! = -1) {if (pathurl.getFile (). charat (0) == '/') jarfile = new Jarfile (filePath.substring (1)); } if (null == jarfile) jarfile = new Jarfile (FilePath); } Enumeración final <JarEntry> e = jarfile.entries (); Entrada ZipEntry; while (e.hasmoreElements ()) {Entry = E.NextElement (); dotypesfilter (basetype, pathurl, resultado, entry.getName (), typenames); }} catch (final ioexception ioex) {}} private void dotypesfilter (final de clase final <?> basetype, final de url pathurl, colección final <string> resultado, cadena final clazzPath, cadena final ... typenames) {if (! ClazzPath.endswith (". Class")) return; final int lastDotidx = ClazzPath.lastIndexof ('.'); if (-1 == lastDotidx) return; Final String typedef = ClazzPath.Substring (0, LastDotidx) .replace ('/', '.'); if (null! = typenames && typenames.length> 0) {final int lastDot = typedef.lastIndexof ('.'); if (lastDot == -1) return; Final String typename = typedef.substring (lastdot + 1); booleano withliked = false; for (cadena final tmptypename: typenames) {if (! typename.contains (tmptypename)) continuar; withliked = verdadero; romper; } if (withliked == false) return; } if (this.typeFilters.IsEmpty ()) {if (null == this.subtypeFilter || this.subtypeFilter.accept (basetype, pathUrl, clazzPath)) dent.Add (typedef); } else {para (final de typeFilter typeFilter: this.typeFilters) {if (! typeFilter.accept (clazzPath)) continuar; if (null == this.subtypeFilter || this.subtypeFilter.accept (basetype, pathUrl, clazzPath)) result.add (typedef); }}} / ** * @param pathUrl * @return * / private boolean aceptación de aceptación (final url pathurl) {if (this.pathurlFilters.isEmpty ()) return true; para (final ipathurlfilter pathurlfilter: this.pathurlfilters) {if (pathurlFilter.accept (pathUrl)) return true; } return false; }}
paquete net.simple.reflect; import java.beans.beans; import java.io.file; import java.io.ioException; import java.io.unsupportedenCodingException; import java.net.Jarurlconnection; import java.net.url; import java.net.urlDecoder; importar java.Utin; java.util.collection; import java.util.collections; import java.util.enumeration; import java.util.list; import java.util.jar.jarentry; import java.util.jar.jarfile; import java.util.zip.zipentry; importar net.simple.reflectect.filter.filter.filter.filter.pathter.pathter.pathur.filter.pathur.pathur.pathurt net.simple.reflect.filter.samplesubInstanceFilter; import net.simple.reflect.filter.typeFilter;/** * * @author li yanfei * @email [email protected] * 2 de noviembre de 2016 a las 3:24:02 PM * */public Final Class Reflectutils {Public Static stating VAR VAR VAR VAR = VARSTART. "$ {"; Public static final String var_end_flag = "}"; Reflexiones estáticas privadas de medidas compartidas; Colección final estática <String> Emp_Coll = Collections.EmptyList (); Public static final void createSharedReflections (String final ... FLIEXTETS) {Reflections finales refs = new Reflections (); refs.AddPathUrlFilter (New PathUrlFilter (FileTexts)); // refs.AddTypeFilter (typeFilter.default); refs.setSubTypeFilter (SamplesUbInstanceFilter.default); Reflectutil.setSharedRefrections (refs); } /*** Este método se utiliza para unir una herramienta de circulación de tipo compartido común. * @param Compartido compartido */ public static final void setSharedReflections (reflexiones finales compartidas) {reflectUtils.sharedReflections = SharedReflections; } /*** Antes de llamar a este método, primero debe establecer la herramienta circunferencial de tipo compartido. Referencia: {@link #setSharedReflections (Reflections)}, * Este método hace que sea más conveniente implementar la clase dada, */ public static final Collection <String> listSubClass (final de la clase <?> Basetype, cadena final ... typenames) {// if (null == Compartido compartido) return emp_coll; // Dado que se pueden agregar nuevas implementaciones de subclase en la etapa de llamadas, es necesario volver a rescatar cada vez. Solo cuando se publica el producto, el método de guardar registros se utiliza para mejorar la velocidad de inicio. return beans.isDesigntime ()? SharedReflamections.getSubtypes (BaseType, Typenames): SharedReflamections.getSubtypeSfast (Basetype); } public static List <Class <? >> ListClassOfPackage (Final Class <?> CType, Extensión de cadena final) {Lista final <class <? >> result = new ArrayList <class <?>> (); Lista final <String> cpath = reflectUtils.listClassCanonicalNameOfPackage (CType, Extension); for (ruta de cadena final: cpath) {try {result.add (class.forname (path, false, thread.currentThread (). getContextClassLoader ())); } Catch (Excepción final e) {// ignorar}} Resultado de retorno; } public static List <String> listClassCanonicalNameOfPackage (final de clase <?> Clazz, extensión de cadena final) {return reflectUtilss.listNameOfPackage (Clazz, Extension, True); } Public static List <String> listClassNameOfPackage (final de clase <?> Clazz, extensión de cadena final) {return reflectUtils.listNameOfPackage (Clazz, Extension, False); } public static list <String> listNameOfPackage (final de clase <?> Clazz, extensión de cadena final, final de booleano final) {return reflectUtilss.listNameOfPackage (clazz.getName (). reemplazar ('.', '/') + ".class", extensión, fullpkgname); } public static list <String> listNameOfPackage (String final ClazzPkg, extensión final de cadena, final de boolean fullpkgname) {Lista final <String> Result = new ArrayList <String> (); final StringBuffer PKGBUF = new StringBuffer (ClazzPkg); if (pkgbuf.charat (0)! = '/') pkgbuf.insert (0, '/'); URL final urlpath = reflectUtils.class.getResource (pkgbuf.toString ()); if (null == UrlPath) Resultado de retorno; Cadena checkedExtenion = extensión; if (! extenion.endswith (". class")) checkedExtenion = extensión + ".class"; if (pkgbuf.toString (). endswith (". class"))) pkgbuf.delete (pkgbuf.lastindexof ("/"), pkgbuf.length ()); pkgbuf.deletecharat (0); final StringBuffer fileUrl = new StringBuffer (); Pruebe {fileurl.append (urlDecoder.decode (urlpath.toExternalForm (), "UTF-8")); } Catch (final UnsupportedEncodingException e1) {fileurl.append (urlpath.toExternalForm ()); } if (fileUrl.ToString (). startswith ("file:")) {fileUrl.Delete (0, 5); // Eliminar archivo: flag if (fileurl.indexof (":")! = -1) fileurl.deletecharat (0); // delete string basado basado = fileurl.substring (0, fileurl.lastIndEn 8); ReflectUtils.DolistNameOfPackAgeIndirectory (nuevo archivo (BaseIR), nuevo archivo (BaseIR), resultado, pkgbuf.toString (), checkExtenion, fullpkgname); } else {reflectUtilss.dolistNameOfPackageInjar (urlpath, urlpath, resultado, pkgbuf.ToString (), checkedexTenion, fullpkgname); } resultado de retorno; } / *** / Private static void dolistNameOfPackageInJar (URL Final URL BaseUrl, URL Final URLPath, Final List <String> Result, String Final String ClazzPkg, Extensión de cadena final, FINAL FINAL FINLPKGNAME) {try {// No funciona con el sistema de archivos: debemos // estar en el caso de un paquete en un archivo jar. final jarurlconnection conn = (jarurlconnection) urlpath.openconnection (); final jarfile jfile = conn.getjarfile (); Enumeración final <JarEntry> e = jfile.entries (); Entrada ZipEntry; String EntryName; while (e.hasmoreElements ()) {Entry = E.NextElement (); EntryName = Entry.getName (); if (entryname.startswith (clazzpkg) && entryname.endswith (extenion)) {if (fullpkgname) result.add (entryname.substring (0, entryname.lastindexof ('.'). Reemplazar ('/', '.')); else resultado.Add (EntryName.Substring (EntryName.LastIndexOf ('/') + 1, EntryName.lastIndexOf ('.'))); }}} Catch (final IOException IOEX) {}} Private static void dolistNameOfPackageIndirectory (Final File BasedIrectory, Directory de archivos Final, Lista final <String> Resultada, String ClazzPkg, Extensión de cadena final, Final Boolean FullPkGname) {Archivo = archivos = Directory.listfiles ();); if (null == archivos) archivos = nuevo archivo [] {}; Cadena Clazzpath; Final int baseLen = Basedirectory.getAbSolutePath (). Longitud () + 1; para (archivo final del archivo: archivos) {if (file.isDirectory ()) {reflexUtils.dolistNameOfPackAgeIndirectory (Basedirectory, File, Result, ClazzPKG, Extension, FullPKGname); } else {if (! File.getName (). Endswith (Extenion)) Continuar; if (fullpkgname) {clazzPath = file.getabsolutePath (). substring (basado ClazzPath = ClazzPath.Substring (0, ClazzPath.length () - 6); result.add (ClazzPath.replace (file.separatorchar, '.')); } else {result.add (file.getName (). Substring (0, file.getName (). Longitud () - 6)); }}}} public static final <T> t initClass (final de cadena implClass, clase final <t> ttype) {return reflectUtilss.initClass (implClass, ttype, true); } public static final <t> t initClass (final de cadena implicClass, clase final <t> ttype, final boolean doinit) {try {object final finalmente = class.forname (implClass, doInit, Thread.CurrentThread (). GetContextClassLoader ()). NewInStance (); return ttype.cast (objeto); } Catch (Final Throwable E) {return null; }}}
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.