??xml version="1.0" encoding="utf-8" standalone="yes"?>久久综合狠狠综合久久综青草,日本精品在线一区,天堂аⅴ在线最新版在线http://www.aygfsteel.com/liuyivan/category/21286.htmlzh-cnWed, 25 Apr 2007 00:41:41 GMTWed, 25 Apr 2007 00:41:41 GMT60[转]q求代码质量: ?AOP q行防M性编E?/title><link>http://www.aygfsteel.com/liuyivan/articles/108600.html</link><dc:creator>p先生</dc:creator><author>p先生</author><pubDate>Thu, 05 Apr 2007 01:40:00 GMT</pubDate><guid>http://www.aygfsteel.com/liuyivan/articles/108600.html</guid><wfw:comment>http://www.aygfsteel.com/liuyivan/comments/108600.html</wfw:comment><comments>http://www.aygfsteel.com/liuyivan/articles/108600.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/liuyivan/comments/commentRss/108600.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/liuyivan/services/trackbacks/108600.html</trackback:ping><description><![CDATA[<p>[原文]http://www.ibm.com/developerworks/cn/java/j-cq01307/index.html<br><br>开发h员测试的主要~点是:l大部分试都是在理想的场景中进行的。在q些情况下ƈ不会出现~陷 —?能导致出现问题的往往是那些边界情c?/p> <p>什么是边界情况呢?比方_?null g入一个ƈ未编写如何处?null 值的Ҏ(gu)中,q就是一U边界情c大多数开发h员通常都不能成功测试这L场景Q因没多大意义。但不管有没有意义,发生了这L情况Q就会抛Z?NullPointerExceptionQ然后整个程序就会崩溃?/p> <p>本月Q我ؓ(zhn)推荐一U多层面的方法,来处理代码中那些不易预料的缺陗尝试ؓ应用E序整合q防御性编E、契U式设计和一U叫?OVal 的易用的通用验证框架?/p> <p><a name=N1007B>敌人暴露出?/a></p> <p>清单 1 中的代码为给定的 Class 对象Q省M java.lang.ObjectQ因为所有对象都最l由它扩展)构徏一个类层次。但如果仔细看的话,(zhn)会注意C个有待发现的潜在~陷Q即该方法对对象值所做的假设?/p> <br><a name=listing1>清单 1. 不检?null 的方?/a><br> <table cellSpacing=0 cellPadding=0 width="100%" border=0> <tbody> <tr> <td> <pre> public static Hierarchy buildHierarchy(Class clzz){ Hierarchy hier = new Hierarchy(); hier.setBaseClass(clzz); Class superclass = clzz.getSuperclass(); if(superclass != null && superclass.getName().equals("java.lang.Object")){ return hier; }else{ while((clzz.getSuperclass() != null) && (!clzz.getSuperclass().getName().equals("java.lang.Object"))){ clzz = clzz.getSuperclass(); hier.addClass(clzz); } return hier; } } </pre> </td> </tr> </tbody> </table> <br> <p>刚编好这个方法,我还没注意到q个~陷Q但׃我狂热地崇拜开发h员测试,于是我编写了一个?TestNG 的常规测试。而且Q我q利用了 TestNG 方便?<code>DataProvider</code> Ҏ(gu),借助该特性,我创Z一个通用的测试用例ƈ通过另一个方法来改变它的参数。运行清?2 中定义的试用例会生两个通过l果Q一切都q{良好Q不是吗Q?/p> <br><a name=listing2>清单 2. 验证两个值的 TestNG 试</a><br> <table cellSpacing=0 cellPadding=0 width="100%" border=0> <tbody> <tr> <td> <pre> import java.util.Vector; import static org.testng.Assert.assertEquals; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class BuildHierarchyTest { @DataProvider(name = "class-hierarchies") public Object[][] dataValues(){ return new Object[][]{ {Vector.class, new String[] {"java.util.AbstractList", "java.util.AbstractCollection"}}, {String.class, new String[] {}} }; } @Test(dataProvider = "class-hierarchies"}) public void verifyHierarchies(Class clzz, String[] names) throws Exception{ Hierarchy hier = HierarchyBuilder.buildHierarchy(clzz); assertEquals(hier.getHierarchyClassNames(), names, "values were not equal"); } } </pre> </td> </tr> </tbody> </table> <br> <p style="FONT-SIZE: 12pt">xQ我q是没有发现~陷Q但一些代码问题却困扰着我。如果有Zl意Cؓ Class 参数传入一?null g怎么样呢Q?a >清单 1</a> 中第 4 行的 clzz.getSuperclass() 调用会抛Z?NullPointerExceptionQ是q样吗?</p> <p>试我的理论很容易;甚至都不用从头开始。仅仅把 {null, null} d到初?BuildHierarchyTest ?dataValues Ҏ(gu)中的多维 Object 数组中,然后再次q行它。我定会得到如图 1 所C的 NullPointerExceptionQ?/p> <br><a name=figX>?1. 可怕的 NullPointerException</a><br><img height=140 alt="可怕的 NullPointerException" src="http://www.ibm.com/developerworks/cn/java/j-cq01307/testng-failure.jpg" width=572 border=0> <br> <p style="FONT-SIZE: 12pt">参见q里?<a >全图</a>?/p> <table cellSpacing=0 cellPadding=0 width="40%" align=right border=0> <tbody> <tr> <td style="FONT-SIZE: 12pt" width=10><img height=1 alt="" src="http://www.ibm.com/i/c.gif" width=10></td> <td style="FONT-SIZE: 12pt"> <table cellSpacing=0 cellPadding=5 width="100%" border=1> <tbody> <tr> <td style="FONT-SIZE: 12pt" bgColor=#eeeeee><a name=N100EE>关于静态分?/a><br> <p style="FONT-SIZE: 12pt">诸如 FindBugs {静态分析工具通过字节码和一pd bug 模式相匹配来验类?JAR 文g从而寻找潜在问题。针Ҏ(gu)例的代码q行 FindBugs 不会 揭示出清?1 中找到的 <code>NullPointerException</code>?/p> </td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <p style="FONT-SIZE: 12pt"><a name=N100FE>防M性编E?/a></p> <p style="FONT-SIZE: 12pt">一旦出现这个问题,下一步就是要拿出Ҏ(gu)的策略。问题是我控制不了这个方法能否接收这U输入。对于这c问题,开发h员通常会用防御性编E技术,该技术专门用来在发生摧毁性后果前捕捉潜在错误?/p> <p>对象验证是处理不定性的一经典的防M性编E策略。相应地Q我会添加一Ҏ(gu)验来验证 <code>clzz</code> 是否?<code>null</code>Q如清单 3 所C。如果其值最lؓ <code>null</code>Q我׃抛出一?<code>RuntimeException</code> 来警告他人注意这个潜在问题?/p> <br><a name=listing3>清单 3. d验证 null 值的?</a><br> <table cellSpacing=0 cellPadding=0 width="100%" border=0> <tbody> <tr> <td> <pre> public static Hierarchy buildHierarchy(Class clzz){ if(clzz == null){ throw new RuntimeException("Class parameter can not be null"); } Hierarchy hier = new Hierarchy(); hier.setBaseClass(clzz); Class superclass = clzz.getSuperclass(); if(superclass != null && superclass.getName().equals("java.lang.Object")){ return hier; }else{ while((clzz.getSuperclass() != null) && (!clzz.getSuperclass().getName().equals("java.lang.Object"))){ clzz = clzz.getSuperclass(); hier.addClass(clzz); } return hier; } } </pre> </td> </tr> </tbody> </table> <br> <p>很自Ӟ我也会编写一个快速测试用例来验证我的验是否真能避?<code>NullPointerException</code>Q如清单 4 所C: </p> <br><a name=listing4>清单 4. 验证 null ?/a><br> <table cellSpacing=0 cellPadding=0 width="100%" border=0> <tbody> <tr> <td> <pre> @Test(expectedExceptions={RuntimeException.class}) public void verifyHierarchyNull() throws Exception{ Class clzz = null; HierarchyBuilder.buildHierarchy(null); } </pre> </td> </tr> </tbody> </table> <br> <p>在本例中Q防御性编E似乎解决了问题。但仅依靠这策略会存在一些缺陗?</p> <p style="FONT-SIZE: 12pt"><a name=N1013A>防M的缺?/a></p> <table cellSpacing=0 cellPadding=0 width="40%" align=right border=0> <tbody> <tr> <td style="FONT-SIZE: 12pt" width=10><img height=1 alt="" src="http://www.ibm.com/i/c.gif" width=10></td> <td style="FONT-SIZE: 12pt"> <table cellSpacing=0 cellPadding=5 width="100%" border=1> <tbody> <tr> <td style="FONT-SIZE: 12pt" bgColor=#eeeeee><a name=N10141>关于断言</a><br> <p style="FONT-SIZE: 12pt">清单 3 使用一个条件来验证 <code>clzz</code> 的|实际?<code>assert</code> 也同样好用。用断aQ无需指定条gQ也不需要指定异常语句。在启用了断a的情况下Q防御性编E的x点全部由 JVM 处理?/p> </td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <p style="FONT-SIZE: 12pt">管防M性编E有效地保证了方法的输入条gQ但如果在一pdҎ(gu)中用它Q不免过于重复。熟(zhn)面向方面编E(?AOPQ的Z会把它认为是横切x点,q意味着防M性编E技术横跨了代码库。许多不同的对象都采用这些语法,管从纯面向对象的观Ҏ(gu)看这些语法跟对象毫不相关?/p> <p>而且Q横切关注点开始渗入到契约式设计(DBCQ的概念中。DBC 是这样一Ҏ(gu)术,它通过在组件的接口昑ּ地陈q每个组件应有的功能和客h的期望值来保pȝ中所有的lg完成它们应尽的职责。从 DBC 的角度讲Q组件应有的功能被认为是后置条gQ本质上是lg的责任,而客h的期望值则普遍被认为是前置条g。另外,在纯 DBC 术语中,遵@ DBC 规则的类针对其将l护的内部一致性与外部世界有一个契U,即h所q的类不变式?/p> <br> <table cellSpacing=0 cellPadding=0 width="100%" border=0> <tbody> <tr> <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td> </tr> </tbody> </table> <br><br> <p><a name=N10167>契约式设?/a></p> <p>我在以前的一关于用 Nice ~程的文章中介绍q?DBC 的概念,Nice 是一门与 JRE 兼容的面向对象编E语aQ它的特Ҏ(gu)侧重于模块性、可表达性和安全性。有的是,Nice q入了功能性开发技术,其中包括了一些在面向斚w~程中的技术。功能性开发得ؓҎ(gu)指定前置条g和后|条件成为可能?/p> <p>管 Nice 支持 DBCQ但它与 Java™ 语言完全不同Q因而很隑ְ其用于开发。幸q的是,很多针对 Java 语言的库也都?DBC 提供了方ѝ每个库都有其优点和~点Q每个库?DBC 内针?Java 语言q行构徏的方法也不同Q但最q的一些新Ҏ(gu)大都利用了 AOP 来更多地?DBC x点包括进来,q些x点基本上q当于Ҏ(gu)的包装器?/p> <p>前置条g在包装过的方法执行前dQ后|条件在该方法完成后d。?AOP 构徏 DBC l构的一个好处(请不要同该语a本n相؜淆!Q是Q可以在不需?DBC x点的环境中将q些l构xQ就像断a能被x一P。以横切的方式对待安全性关注点的真正妙处是Q可以有效地重用 q些x炏V众所周知Q重用是面向对象~程的一个基本原则。AOP 如此完美地补充了 OOP N不是一件极好的事情吗? </p> <br> <table cellSpacing=0 cellPadding=0 width="100%" border=0> <tbody> <tr> <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td> </tr> </tbody> </table> <br><br> <p><a name=N1017A>l合?OVal ?AOP</a></p> <p>OVal 是一个通用的验证框Ӟ它通过 AOP 支持单的 DBC l构q明地允许Q?</p> <ul> <li>为类字段和方法返回值指定约束条? <li>为结构参数指定约束条? <li>为方法参数指定约束条?</li> </ul> <p>此外QOVal q带来大量预定义的约束条Ӟq让创徏新条件变得相当容易?/p> <p>׃ OVal 使用 AspectJ ?AOP 实现来ؓ DBC 概念定义Q所以必d AspectJ q入一个?OVal 的项目中。对于不熟?zhn)?AOP ?AspectJ 的h们来_好消息是q不隑֮玎ͼ且?OVal Q甚x创徏新的U束条gQƈ不需要真正对斚wq行~码Q只需~写一个简单的自引导程序即可,该程序会?OVal 所附带的默认方面植入?zhn)的代码中?/p> <p>在创个自引导E序斚w前,要先下蝲 AspectJ。具体地_(zhn)需要将 <code>aspectjtools</code> ?<code>aspectjrt</code> JAR 文gq入(zhn)的构徏中来~译所需的自引导E序斚wq将其编入?zhn)的代码中?/p> <br> <table cellSpacing=0 cellPadding=0 width="100%" border=0> <tbody> <tr> <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td> </tr> </tbody> </table> <br><br> <p><a name=N101A2>自引?AOP</a></p> <p>下蝲?AspectJ 后,下一步是创徏一个可扩展 OVal <code>GuardAspect</code> 的方面。它本n不需要做什么,如清?5 所C。请保文g的扩展名?.aj l束Q但不要试着用常规的 <code>javac</code> 对其q行~译?/p> <br><a name=listing5>清单 5. DefaultGuardAspect 自引导程序方?/a><br> <table cellSpacing=0 cellPadding=0 width="100%" border=0> <tbody> <tr> <td> <pre> import net.sf.oval.aspectj.GuardAspect; public aspect DefaultGuardAspect extends GuardAspect{ public DefaultGuardAspect(){ super(); } } </pre> </td> </tr> </tbody> </table> <br> <p>AspectJ 引入了一?Ant dQ称?<code>iajc</code>Q充当着 <code>javac</code> 的角Ԍ此过E对斚wq行~译q将其编入主体代码中。在本例中,只要是我指定?OVal U束条g的地方,?OVal 代码中定义的逻辑׃~入我的代码Q进而充当v前置条g和后|条件?/p> <p>误?<code>iajc</code> 代替?<code>javac</code>。例如,清单 6 是我?Ant build.xml 文g的一个代码片D,其中对代码进行了~译q把通过代码标注发现的所?OVal 斚w~入q来Q如下所C:</p> <br><a name=listing6>清单 6. ?AOP ~译?Ant 构徏文g片段</a><br> <table cellSpacing=0 cellPadding=0 width="100%" border=0> <tbody> <tr> <td> <pre> <target name="aspectjc" depends="get-deps"> <taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties"> <classpath> <path refid="build.classpath" /> </classpath> </taskdef> <iajc destdir="${classesdir}" debug="on" source="1.5"> <classpath> <path refid="build.classpath" /> </classpath> <sourceroots> <pathelement location="src/java" /> <pathelement location="test/java" /> </sourceroots> </iajc> </target> </pre> </td> </tr> </tbody> </table> <br> <p>?OVal 铺好了\、ؓ AOP q程做了引导之后Q就可以开始?Java 5 标注来ؓ代码指定单的U束条g了?/p> <br> <table cellSpacing=0 cellPadding=0 width="100%" border=0> <tbody> <tr> <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td> </tr> </tbody> </table> <br><br> <p><a name=N101DF>OVal 的可重用U束条g</a></p> <p>?OVal 为方法指定前|条件必dҎ(gu)参数q行标注。相应地Q当调用一个用 OVal U束条g标注q的Ҏ(gu)ӞOVal 会在该方法真正执行前 验证该约束条件?/p> <p>在我的例子中Q我惌指定?<code>Class</code> 参数的gؓ <code>null</code> Ӟ<code>buildHierarchy</code> Ҏ(gu)不能被调用。OVal 通过 <code>@NotNull</code> 标注支持此约束条Ӟ该标注在Ҏ(gu)所需的所有参数前指定。也要注意,M惌使用 OVal U束条g的类也必dcdơ上指定 <code>@Guarded</code> 标注Q就像我在清?7 中所做的那样Q?/p> <br><a name=listing7>清单 7. OVal U束条g</a><br> <table cellSpacing=0 cellPadding=0 width="100%" border=0> <tbody> <tr> <td> <pre> import net.sf.oval.annotations.Guarded; import net.sf.oval.constraints.NotNull; @Guarded public class HierarchyBuilder { public static Hierarchy buildHierarchy(@NotNull Class clzz){ Hierarchy hier = new Hierarchy(); hier.setBaseClass(clzz); Class superclass = clzz.getSuperclass(); if(superclass != null && superclass.getName().equals("java.lang.Object")){ return hier; }else{ while((clzz.getSuperclass() != null) && (!clzz.getSuperclass().getName().equals("java.lang.Object"))){ clzz = clzz.getSuperclass(); hier.addClass(clzz); } return hier; } } } </pre> </td> </tr> </tbody> </table> <br> <p>通过标注指定q个U束条g意味着我的代码不再会被重复的条件弄得ؕ七八p,q些条g?<code>null</code> |q且一旦找到该值就会抛出异常。现在这w辑?OVal 处理Q且处理的方法有些相?—?事实上,如果q反了约束条ӞOVal 会抛Z?<code>ConstraintsViolatedException</code>Q它?<code>RuntimeException</code> 的子cR?</p> <p>当然Q我下一步就要编?<code>HierarchyBuilder</code> cd <a >清单 5</a> 中相应的 <code>DefaultGuardAspect</code> cR我?<a >清单 6</a> 中的 <code>iajc</code> d来实现这一目的Q这hp?OVal 的行为编入我的代码中了?</p> <p>接下来,我更?<a >清单 4</a> 中的试用例来验证是否抛Z一?<code>ConstraintsViolatedException</code>Q如清单 8 所C:</p> <br><a name=listing8>清单 8. 验证是否抛出?ConstraintsViolatedException</a><br> <table cellSpacing=0 cellPadding=0 width="100%" border=0> <tbody> <tr> <td> <pre> @Test(expectedExceptions={ConstraintsViolatedException.class}) public void verifyHierarchyNull() throws Exception{ Class clzz = null; HierarchyBuilder.buildHierarchy(clzz); } </pre> </td> </tr> </tbody> </table> <br> <p><a name=N1024C>指定后置条g</a></p> <p>正如(zhn)所见,指定前置条g其实相当Ҏ(gu)Q指定后|条件的q程也是一栗例如,如果我想Ҏ(gu)有调?<code>buildHierarchy</code> 的程序保证它不会q回 <code>null</code> |q样Q这些调用程序就不需要再查这个了Q,我可以在Ҏ(gu)声明之上攄一?<code>@NotNull</code> 标注Q如清单 9 所C:</p> <br><a name=listing9>清单 9. OVal 中的后置条g</a><br> <table cellSpacing=0 cellPadding=0 width="100%" border=0> <tbody> <tr> <td> <pre> @NotNull public static Hierarchy buildHierarchy(@NotNull Class clzz){ //method body } </pre> </td> </tr> </tbody> </table> <br> <p>当然Q?code>@NotNull</code> l不?OVal 提供的惟一U束条gQ但我发现它能非常有效地限制q些令h讨厌?<code>NullPointerException</code>Q或臛_能够快速地暴露 它们?/p> <p><a name=N1027B>更多?OVal U束条g</a></p> <p>OVal 也支持在Ҏ(gu)调用前或后对cL员进行预先验证。这U机制具有限刉对特定约束条件的重复条g试的好处,如集合大或之前讨论q的?<code>null</code> 的情c?/p> <p>例如Q在清单 10 中,我?<code>HierarchyBuilder</code> 定义了一个ؓcdơ构建报告的 Ant d。请注意 <code>execute()</code> Ҏ(gu)是如何调?<code>validate</code> 的,后者会依次验证 <code>fileSet</code> cL员是否含|如果不含Q会抛出一个异常,因ؓ没有了要评估的类Q该报告不能q行?/p> <br><a name=listing10>清单 10. 带条件检验的 HierarchyBuilderTask </a><br> <table cellSpacing=0 cellPadding=0 width="100%" border=0> <tbody> <tr> <td> <pre> public class HierarchyBuilderTask extends Task { private Report report; private List fileSet; private void validate() throws BuildException{ if(!(this.fileSet.size() > 0)){ throw new BuildException("must supply classes to evaluate"); } if(this.report == null){ this.log("no report defined, printing XML to System.out"); } } public void execute() throws BuildException { validate(); String[] classes = this.getQualifiedClassNames(this.fileSet); Hierarchy[] hclz = new Hierarchy[classes.length]; try{ for(int x = 0; x < classes.length; x++){ hclz[x] = HierarchyBuilder.buildHierarchy(classes[x]); } BatchHierarchyXMLReport xmler = new BatchHierarchyXMLReport(new Date(), hclz); this.handleReportCreation(xmler); }catch(ClassNotFoundException e){ throw new BuildException("Unable to load class check classpath! " + e.getMessage()); } } //more methods below.... } </pre> </td> </tr> </tbody> </table> <br> <p>因ؓ我用的是 OValQ所以我可以完成下列dQ?/p> <ul> <li>?<code>fileSet</code> cL员指定一个约束条Ӟ保使用 <code>@Size</code> 标注时其大小L臛_?1 或更大? <li>保在?<code>@PreValidateThis</code> 标注调用 <code>execute()</code> Ҏ(gu)?验证q个U束条g?</li> </ul> <p>q两步让我能够有效地去除 <code>validate()</code> Ҏ(gu)中的条g验,?OVal 为我完成q些Q如清单 11 所C: </p> <br><a name=listing11>清单 11. l过改进、无条g验的 HierarchyBuilderTask</a><br> <table cellSpacing=0 cellPadding=0 width="100%" border=0> <tbody> <tr> <td> <pre> @Guarded public class HierarchyBuilderTask extends Task { private Report report; @Size(min = 1) private List fileSet; private void validate() throws BuildException { if (this.report == null) { this.log("no report defined, printing XML to System.out"); } } @PreValidateThis public void execute() throws BuildException { validate(); String[] classes = this.getQualifiedClassNames(this.fileSet); Hierarchy[] hclz = new Hierarchy[classes.length]; try{ for(int x = 0; x < classes.length; x++){ hclz[x] = HierarchyBuilder.buildHierarchy(classes[x]); } BatchHierarchyXMLReport xmler = new BatchHierarchyXMLReport(new Date(), hclz); this.handleReportCreation(xmler); }catch(ClassNotFoundException e){ throw new BuildException("Unable to load class check classpath! " + e.getMessage()); } } //more methods below.... } </pre> </td> </tr> </tbody> </table> <br> <p>清单 11 中的 <code>execute()</code> 一l调用(?Ant 完成Q,OVal ׃验证 <code>fileSet</code> 成员。如果其为空Q就意味着没有指定M要评估的c,׃抛出一?<code>ConstraintsViolatedException</code>。这个异怼暂停q一q程Q就像初始代码一P只不q初始代码会抛出一?<code>BuildException</code>?/p> <img src ="http://www.aygfsteel.com/liuyivan/aggbug/108600.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/liuyivan/" target="_blank">p先生</a> 2007-04-05 09:40 <a href="http://www.aygfsteel.com/liuyivan/articles/108600.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> վ֩ģ壺 <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ͽ</a>| <a href="http://" target="_blank">üɽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ƽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ժ</a>| <a href="http://" target="_blank">ͷ</a>| <a href="http://" target="_blank">ĺ</a>| <a href="http://" target="_blank">ְ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ӷ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">կ</a>| <a href="http://" target="_blank">ӳ</a>| <a href="http://" target="_blank">ɽ</a>| <a href="http://" target="_blank">¡</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">佭</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">²</a>| <a href="http://" target="_blank">Ӵ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ij</a>| <a href="http://" target="_blank">Ϫ</a>| <a href="http://" target="_blank">׼</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ˮ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">®</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">˳</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>