国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

聊一聊Java反射

2019-11-26 13:36:27
字體:
來源:轉載
供稿:網友

這次提到的Java反射涉及的代碼比較多。因為工作中經常用到反射,對代碼做了很多抽象以及過濾器。雖然代碼量很多,但是簡單易用,過濾插件也易修改。

下面介紹下工作中哪些地方比較容易用到反射。比如插件或者過濾器,如果抽象的子類比較少,配置成XML等結構也是可以達到同樣的效果。如果希望靈活一些,添加了插件或者過濾器代碼子類后希望可以直接使用。可能反射會比較好點,通過掃描所有class或者jar文件,得到所有繼承的子類。如果每次調用都掃描所有的文件會比較影響性能。所以在實現里面加入反射緩存,對所要獲取反射子類時涉及的所有參數作為一個key緩存所有的反射結果。下次如果是同樣的key,就不在重新掃描。

代碼示例如下:

public static void main(String[] args) { //設置掃描范圍,可以是class文件所在位置例如bin下或者是mysql開頭或者mysql結尾的jar, //設置為""為全部都掃描,這種比較耗時 ReflectUtils.createSharedReflections("classes", "bin", "mysql"); try {  //調試階段可以設置每次都全掃描  //Beans.setDesignTime(true);  final Collection<String> subTypes = ReflectUtils.listSubClass(IA.class);//  for (final String subType : subTypes) {  //這里獲取的是所有繼承IA的子類  System.out.println(subType);  final IA impl = ReflectUtils.initClass(subType, IA.class);  if (null == impl)   continue;  //通過該方式,可以統一做操作,  impl.print();  } } catch (Exception e) {  e.printStackTrace(); } }

代碼執行結果:

//緩存文件,避免每次調用反射都重新掃描//如果刪除該文件,再次調用反射時,會重新掃描,一般會在代碼里面有添加子類的時候會刪除該文件XmlUtils.readXml failure:./configuration.REF (系統找不到指定的文件。)net.simple.reflect.test.Bnet.simple.reflect.test.Bnet.simple.reflect.test.Dnet.simple.reflect.test.V

具體的類里面如何實現的大家就看下源碼吧,這里貼出兩個核心類的代碼。源碼地址:https://git.oschina.net/eliyanfei/api_tools

package 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.Enumeration;import 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 org.w3c.dom.Document;import org.w3c.dom.Element;/** *  * @author 李巖飛 * @email eliyanfei@126.com  * 2016年11月2日 下午3:23:49 * */public final class Reflections { private final Collection<URL> pathUrls; private final Collection<IPathURLFilter> pathURLfilters; private final Collection<ITypeFilter> typeFilters; private ISubTypeFilter subTypeFilter; public Reflections() { typeFilters = new ArrayList<ITypeFilter>(); pathURLfilters = new ArrayList<IPathURLFilter>(); this.pathUrls = ClasspathHelper.getUrlsForCurrentClasspath(); } public Reflections(final Collection<URL> pathUrls) { this.pathUrls = pathUrls; typeFilters = new ArrayList<ITypeFilter>(); pathURLfilters = new ArrayList<IPathURLFilter>(); } /** * @param subTypeFilter *      the subTypeFilter to set */ public void setSubTypeFilter(final ISubTypeFilter subTypeFilter) { this.subTypeFilter = subTypeFilter; } /** * @return the subTypeFilter */ public ISubTypeFilter getSubTypeFilter() { return subTypeFilter; } public Reflections addPathURLFilter(final IPathURLFilter pathURLFilter) { if (null == pathURLFilter)  return this; if (!this.pathURLfilters.contains(pathURLFilter))  this.pathURLfilters.add(pathURLFilter); return this; } public Reflections addTypeFilter(final ITypeFilter typeFilter) { if (null == typeFilter)  return this; if (!this.typeFilters.contains(typeFilter))  this.typeFilters.add(typeFilter); return this; } private static final String histFile = "./configuration.REF"; private Document histDom; public Collection<String> getSubTypesFast(final Class<?> baseType) {//, final String... typeNames //首先過濾出當前允許掃描的路徑 final StringBuilder bufPathsId = new StringBuilder(32); final Map<File, URL> fileUrls = new LinkedHashMap<File, URL>(8); for (final URL pathUrl : pathUrls) {  if (!acceptPathUrl(pathUrl))  continue;  File file = null;  try {  file = new File(URLDecoder.decode(pathUrl.getFile(), "UTF-8"));  } catch (final Exception e) {  file = new File(pathUrl.getFile());  }  fileUrls.put(file, pathUrl);  if (!file.exists())//is url file?ignore  continue;  bufPathsId.append(file.getName()).append(file.lastModified()); } final String domId = MD5.getHashString(bufPathsId.toString()); if (null == histDom)  histDom = W3cUtils.readXml(histFile); if (null == histDom)  histDom = W3cUtils.newDom("R"); Element rootEle = histDom.getDocumentElement(); if (null == rootEle)  histDom.appendChild(rootEle = histDom.createElement("R")); if (!domId.equals(rootEle.getAttribute("id"))) {  rootEle.getParentNode().removeChild(rootEle);  histDom.appendChild(rootEle = histDom.createElement("R"));  rootEle.setAttribute("id", domId); } final String baseTypeId = MD5.getHashString(baseType.getName()); Element refEle = W3cUtils.firstChildElement(rootEle, "E", "id", baseTypeId); if (null != refEle) {  final List<Element> valueEles = W3cUtils.childElementList(refEle, "F");  final Collection<String> result = new ArrayList<String>(valueEles.size());  for (final Element valueEle : valueEles) {  result.add(new String(Base64.decodeFast(valueEle.getAttribute("id"))));  }  return result; } final ThreadPool<ListSubTypes> pool = new ThreadPool<ListSubTypes>(); for (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();//for debug } final Collection<String> result = new ArrayList<String>(); for (final ListSubTypes task : pool.getThreadRunables()) {  result.addAll(task.result); } refEle = W3cUtils.addEle(rootEle, "E"); refEle.setAttribute("id", baseTypeId); for (final String itm : result) {  W3cUtils.addEle(refEle, "F").setAttribute("id", Base64.encodeToString(itm.getBytes(), false)); } try {  W3cUtils.writeXmlDocument(histFile, histDom); } catch (final Exception e) { } return result; } /** * @see {@link ReflectUtils#createSharedReflections(String...)} * @see {@link ReflectUtils#setSharedReflections(Reflections)} * @see {@link ReflectUtils#listSubClass(Class)} * @param baseType * @return */ public Collection<String> getSubTypes(final Class<?> baseType, final String... typeNames) {// final ThreadPool<ListSubTypes> pool = new ThreadPool<ListSubTypes>(); for (final URL pathUrl : pathUrls) {  if (!acceptPathUrl(pathUrl))  continue;  File file = null;  try {  file = new File(URLDecoder.decode(pathUrl.getFile(), "UTF-8"));  } catch (final Exception e) {  file = new File(pathUrl.getFile());  }  pool.execute(new ListSubTypes(baseType, file, pathUrl, typeNames)); } try {  pool.shutdown(3, TimeUnit.MINUTES); } catch (final InterruptedException e) {  e.printStackTrace();//for debug } final Collection<String> result = new ArrayList<String>(); for (final ListSubTypes task : pool.getThreadRunables()) {  result.addAll(task.result); } return result; } class ListSubTypes implements Runnable { final File file; final Class<?> baseType; final URL pathUrl; final String[] typeNames; public ListSubTypes(final Class<?> baseType, final File file, final URL pathUrl, final String... typeNames) {  this.baseType = baseType;  this.file = file;  this.pathUrl = pathUrl;  this.typeNames = typeNames; } Collection<String> result = new ArrayList<String>(4); @Override public void run() {  if (file.isDirectory()) {  listSubTypesFromDirectory(file, baseType, pathUrl, file, result, typeNames);  } else  listSubTypesFromJar(baseType, pathUrl, result, typeNames); } } /** * @param baseType * @param pathUrl * @param result */ public void listSubTypesFromDirectory(final File baseDirectory, final Class<?> baseType, final URL pathUrl, final File directory,  final Collection<String> result, final String... typeNames) { File[] files = directory.listFiles(); if (null == files)  files = new File[] {}; String clazzPath; final int baseDirLen = baseDirectory.getAbsolutePath().length() + 1; for (final File file : files) {  if (file.isDirectory()) {  listSubTypesFromDirectory(baseDirectory, baseType, pathUrl, file, result, typeNames);  } else {  clazzPath = file.getAbsolutePath().substring(baseDirLen);  clazzPath = clazzPath.replace('//', '/');  doTypesFilter(baseType, pathUrl, result, clazzPath, typeNames);  } } } /** * @param baseType * @param pathUrl * @param result */ public void listSubTypesFromJar(final Class<?> baseType, URL pathUrl, final Collection<String> result, final String... typeNames) { try {  // It does not work with the filesystem: we must  // be in the case of a package contained in a jar file.  JarFile jarFile = null;  try {  if ("file".equals(pathUrl.getProtocol()))   pathUrl = new URL("jar:" + pathUrl.toExternalForm() + "!/");  jarFile = ((JarURLConnection) pathUrl.openConnection()).getJarFile();  } catch (final Exception e) {  final String filePath = pathUrl.getFile();  // if on win platform  if (filePath.indexOf(':') != -1) {   if (pathUrl.getFile().charAt(0) == '/')   jarFile = new JarFile(filePath.substring(1));  }  if (null == jarFile)   jarFile = new JarFile(filePath);  }  final Enumeration<JarEntry> e = jarFile.entries();  ZipEntry entry;  while (e.hasMoreElements()) {  entry = e.nextElement();  doTypesFilter(baseType, pathUrl, result, entry.getName(), typeNames);  } } catch (final IOException ioex) { } } private void doTypesFilter(final Class<?> baseType, final URL pathUrl, final Collection<String> result, final String clazzPath,  final String... 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);  boolean withLiked = false;  for (final String tmpTypeName : typeNames) {  if (!typeName.contains(tmpTypeName))   continue;  withLiked = true;  break;  }  if (withLiked == false)  return; } if (this.typeFilters.isEmpty()) {  if (null == this.subTypeFilter || this.subTypeFilter.accept(baseType, pathUrl, clazzPath))  result.add(typeDef); } else {  for (final ITypeFilter typeFilter : this.typeFilters) {  if (!typeFilter.accept(clazzPath))   continue;  if (null == this.subTypeFilter || this.subTypeFilter.accept(baseType, pathUrl, clazzPath))   result.add(typeDef);  } } } /** * @param pathUrl * @return */ private boolean acceptPathUrl(final URL pathUrl) { if (this.pathURLfilters.isEmpty())  return true; for (final IPathURLFilter pathURLFilter : this.pathURLfilters) {  if (pathURLFilter.accept(pathUrl))  return true; } return false; }}

package 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;import java.util.ArrayList;import 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;import net.simple.reflect.filter.PathURLFilter;import net.simple.reflect.filter.SampleSubInstanceFilter;import net.simple.reflect.filter.TypeFilter;/** *  * @author 李巖飛 * @email eliyanfei@126.com  * 2016年11月2日 下午3:24:02 * */public final class ReflectUtils { public static final String VAR_START_FLAG = "${"; public static final String VAR_END_FLAG = "}"; private static Reflections sharedReflections; static final Collection<String> EMP_COLL = Collections.emptyList(); public static final void createSharedReflections(final String... filterExts) { final Reflections refs = new Reflections(); refs.addPathURLFilter(new PathURLFilter(filterExts));// refs.addTypeFilter(TypeFilter.DEFAULT); refs.setSubTypeFilter(SampleSubInstanceFilter.DEFAULT); ReflectUtils.setSharedReflections(refs); } /** * 此方法用于綁定一個通用的共享類型遍列工具. * @param sharedReflections */ public static final void setSharedReflections(final Reflections sharedReflections) { ReflectUtils.sharedReflections = sharedReflections; } /** * 調用此方法之前必須先設置共享的類型遍列工具,參考:{@link #setSharedReflections(Reflections)}, * 此方法主要使更方便的遍列給定類的實現, */ public static final Collection<String> listSubClass(final Class<?> baseType, final String... typeNames) {// if (null == sharedReflections)  return EMP_COLL; //調用階段由于可能增加新的子類實現,需要每次都重新掃描,只有在發布的產品時使用保存記錄的方法以提高啟動速度. return Beans.isDesignTime() ? sharedReflections.getSubTypes(baseType, typeNames) : sharedReflections.getSubTypesFast(baseType); } public static List<Class<?>> listClassOfPackage(final Class<?> cType, final String extenion) { final List<Class<?>> result = new ArrayList<Class<?>>(); final List<String> cPath = ReflectUtils.listClassCanonicalNameOfPackage(cType, extenion); for (final String path : cPath) {  try {  result.add(Class.forName(path, false, Thread.currentThread().getContextClassLoader()));  } catch (final Exception e) {  // ignore  } } return result; } public static List<String> listClassCanonicalNameOfPackage(final Class<?> clazz, final String extenion) { return ReflectUtils.listNameOfPackage(clazz, extenion, true); } public static List<String> listClassNameOfPackage(final Class<?> clazz, final String extenion) { return ReflectUtils.listNameOfPackage(clazz, extenion, false); } public static List<String> listNameOfPackage(final Class<?> clazz, final String extenion, final boolean fullPkgName) { return ReflectUtils.listNameOfPackage(clazz.getName().replace('.', '/') + ".class", extenion, fullPkgName); } public static List<String> listNameOfPackage(final String clazzPkg, final String extenion, final boolean fullPkgName) { final List<String> result = new ArrayList<String>(); final StringBuffer pkgBuf = new StringBuffer(clazzPkg); if (pkgBuf.charAt(0) != '/')  pkgBuf.insert(0, '/'); final URL urlPath = ReflectUtils.class.getResource(pkgBuf.toString()); if (null == urlPath)  return result; String checkedExtenion = extenion; if (!extenion.endsWith(".class"))  checkedExtenion = extenion + ".class"; if (pkgBuf.toString().endsWith(".class"))  pkgBuf.delete(pkgBuf.lastIndexOf("/"), pkgBuf.length()); pkgBuf.deleteCharAt(0); final StringBuffer fileUrl = new StringBuffer(); try {  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);// delete file: flag  if (fileUrl.indexOf(":") != -1)  fileUrl.deleteCharAt(0);// delete flag  final String baseDir = fileUrl.substring(0, fileUrl.lastIndexOf("classes") + 8);  ReflectUtils.doListNameOfPackageInDirectory(new File(baseDir), new File(baseDir), result, pkgBuf.toString(), checkedExtenion, fullPkgName); } else {  ReflectUtils.doListNameOfPackageInJar(urlPath, urlPath, result, pkgBuf.toString(), checkedExtenion, fullPkgName); } return result; } /** */ private static void doListNameOfPackageInJar(final URL baseUrl, final URL urlPath, final List<String> result, final String clazzPkg, final String extenion, final boolean fullPkgName) { try {  // It does not work with the filesystem: we must  // be in the case of a package contained in a jar file.  final JarURLConnection conn = (JarURLConnection) urlPath.openConnection();  final JarFile jfile = conn.getJarFile();  final Enumeration<JarEntry> e = jfile.entries();  ZipEntry entry;  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('.')).replace('/', '.'));   else   result.add(entryname.substring(entryname.lastIndexOf('/') + 1, entryname.lastIndexOf('.')));  }  } } catch (final IOException ioex) { } } private static void doListNameOfPackageInDirectory(final File baseDirectory, final File directory, final List<String> result, final String clazzPkg, final String extenion,  final boolean fullPkgName) { File[] files = directory.listFiles(); if (null == files)  files = new File[] {}; String clazzPath; final int baseDirLen = baseDirectory.getAbsolutePath().length() + 1; for (final File file : files) {  if (file.isDirectory()) {  ReflectUtils.doListNameOfPackageInDirectory(baseDirectory, file, result, clazzPkg, extenion, fullPkgName);  } else {  if (!file.getName().endsWith(extenion))   continue;  if (fullPkgName) {   clazzPath = file.getAbsolutePath().substring(baseDirLen);   clazzPath = clazzPath.substring(0, clazzPath.length() - 6);   result.add(clazzPath.replace(File.separatorChar, '.'));  } else {   result.add(file.getName().substring(0, file.getName().length() - 6));  }  } } } public static final <T> T initClass(final String implClass, final Class<T> tType) { return ReflectUtils.initClass(implClass, tType, true); } public static final <T> T initClass(final String implClass, final Class<T> tType, final boolean doInit) { try {  final Object object = Class.forName(implClass, doInit, Thread.currentThread().getContextClassLoader()).newInstance();  return tType.cast(object); } catch (final Throwable e) {  return null; } }}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 万宁市| 六盘水市| 亳州市| 聊城市| 南昌县| 和硕县| 隆化县| 阜康市| 深泽县| 哈密市| 若尔盖县| 中宁县| 华池县| 望城县| 丹江口市| 莫力| 怀化市| 永州市| 西昌市| 新蔡县| 漾濞| 登封市| 蒙阴县| 泸溪县| 忻城县| 桂林市| 新平| 麦盖提县| 东宁县| 南投市| 仁化县| 汤阴县| 澎湖县| 乃东县| 吉林省| 忻城县| 郴州市| 锦屏县| 班玛县| 桃园市| 沽源县|