激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|

服務器之家 - 編程語言 - JAVA教程 - 聊一聊Java反射

聊一聊Java反射

2020-07-01 11:28李巖飛 JAVA教程

工作中哪些地方比較容易用到反射,這篇文章就為大家介紹了工作中常用到的Java反射,具有一定的參考價值,感興趣的小伙伴們可以參考一下

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

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

代碼示例如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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();
 }
 }

代碼執行結果:

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
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 [email protected]
 * 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;
 }
}

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
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 [email protected]
 * 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;
 }
 }
}

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 成人做爽爽爽爽免费国产软件 | 亚洲午夜一区二区三区 | 激情国产视频 | 97久久曰曰久久久 | 午夜精品久久久久久久99热浪潮 | xfplay噜噜av | 黄色毛片视频在线观看 | 在线中文字幕观看 | 成人在线免费观看小视频 | 日韩毛片在线看 | 午夜精品毛片 | 成年人小视频在线观看 | 欧美一级毛片美99毛片 | 亚洲欧美日韩精品久久亚洲区 | 久草视频在线资源 | 日本成年免费网站 | 国产亚洲精品视频中文字幕 | 日本在线视频一区二区三区 | 成人爽a毛片免费啪啪红桃视频 | 国产一级做a爱片在线看免 日日草夜夜 | 国产毛片在线看 | 日日摸夜夜骑 | 成人短视频在线观看免费 | 136福利视频 | 在线免费观看麻豆 | 请播放一级毛片 | 日本成人在线免费 | 亚州欧美视频 | 91色一区二区三区 | bt 自拍 另类 综合 欧美 | 午夜视频在线观看免费视频 | 久久精品国产亚洲7777 | 国产精品视频导航 | 精品一区二区三区毛片 | 久久国产精品影视 | 久久久一区二区三区精品 | 女人一区二区三区 | 欧美日韩亚洲一区二区三区 | 精品国产视频一区二区三区 | 艹男人的日日夜夜 | 久久精品网址 |