第 8 章 源代码级的元数据支持

8.1. 源代码级的元数据

源代码级的元数据是对程序元素:通常为类和/或方法的 attribute 或者叫annotation的扩充。

举例来说,我们可以象下面一样给一个类添加元数据:

/*** Normal comments* @@org.springframework.transaction.interceptor.DefaultTransactionAttribute()*/
public class PetStoreImpl implements PetStoreFacade, OrderService {

我们也可以添加元数据到一个方法上:

/*** Normal comments* @@org.springframework.transaction.interceptor.RuleBasedTransactionAttribute ()* @@org.springframework.transaction.interceptor.RollbackRuleAttribute (Exception.class)* @@org.springframework.transaction.interceptor.NoRollbackRuleAttribute ("ServletException")*/
public void echoException(Exception ex) throws Exception {....
}

这两个例子都使用了Jakarta Commons Attributes的格式。

源代码级的元数据随着Microsoft的.NET平台的发布被介绍给大众,它使用了源代码级的attribute 来控制事务,缓冲池(pooling)和一些其他的行为。

这种方法的价值已经被J2EE社区的人们认识到了。举例来说,跟EJB中清一色使用的传统的XML部署描述文 件比起来它要简单很多。XML描述文件适合于把一些东西从程序源代码中提取出来,一些重要的企业级设 定——特别是事务特性——本来属于程序代码。并不像EJB规范中设想的那样,调整一个方法的事务特性根本 没有什么意义。

虽然元数据attribute主要用于框架的基础架构来描述应用程序的类需要的业务, 但是也可以在运行时查询元数据attribute。这是与XDoclet这样的解决方案的关键区别,XDoclet 主要把元数据作为生成代码的一种方式,比如生成EJB类。

这一段包括了几个解决方案:

  • JSR-175:标准的Java元数据实现,在Java 1.5中提供。 但是我们现在就需要一个解决方案,通常情况下可能还需要一个外观(facade)。

  • XDoclet:成熟的解决方案,主要用于代码生成

  • 其它不同的开源attribute实现,在JSR-175的发布 悬而未决的情况下,它们当中的Commons Attributes看来是最有前途的。所有的这些实现都需要一 个特定的前编译或后编译的步骤。

8.2. Spring的元数据支持

为了与它提供的其他重要概念的抽象相一致,Spring提供了一个对元数据实现的外观(facade), 以org.springframework.metadata.Attributes这个接口的形式来表示。

这样一个外观很有价值,因为下面几个原因:

  • 目前还没有一个标准的元数据解决方案。 Java 1.5版本会提供一个,但是在Spring1.0版本的时候, Java 1.5仍是beta版本。而且,至少两年内还是需要对1.3和1.4版本的应用程序提供元数据支持。 现在Spring打算提供一些可以工作的解决方案: 在一个重要的环境下等待1.5,并不是个好的选择.

  • 目前的元数据API,例如Commons Attributes(被Spring 1.0使用), 测试起来很困难。Spring提供了一个简单的更容易模拟的元数据接口。

  • 即使当Java 1.5在语言级别提供了对元数据的支持时,提供了一个如此的抽象仍然是有价值的:

    • JSR-175的元数据是静态的。它是在编译时与某一个类关联,而在部署环境下是不可改变的。 这里会需要多层次的元数据,以支持在部署时重载某些attribute的值--举例来说, 在一个XML文件中定义用于覆盖的attribute。

    • JSR-175的元数据是通过Java反射API返回的。这使得在测试时无法模拟元数据。 Spring提供了一个简单的接口来允许这种模拟。

虽然Spring在Java 1.5达到它的GA版本之前将支持JSR-175,但仍会继续提供一个attribute抽象API。

Spring的Attributes接口看起来是这样的:

public interface Attributes {Collection getAttributes(Class targetClass);Collection getAttributes(Class targetClass, Class filter);Collection getAttributes(Method targetMethod);Collection getAttributes(Method targetMethod, Class filter);Collection getAttributes(Field targetField);Collection getAttributes(Field targetField, Class filter);
}

这是个最普通不过的命名者接口。JSR-175能提供更多的功能,比如定义在方法参数上的attributes。 在1.0版本时,Spring目的在于提供元数据的一个子集,使得能象EJB或.NET一样提供有效的声明式企业级服务。 1.0版本以后,Spring将提供更多的元数据方法。

注意到该接口像.NET一样提供了Object类型的attibute。 这使得它区别于一些仅提供String类的attribute的attribute系统, 比如Nanning Aspects和JBoss 4(在DR2版本时)。支持Object类型的attribute有一个显著的优点。 它使attribute含有类层次,还可以使attribute能够灵活的根据它们的配置参数起作用。

对于大多数attribute提供者来说,attribute类的配置是通过构造函数参数或JavaBean的属性完成的。Commons Attributes同时支持这两种方式。

同所有的Spring抽象API一样,Attributes是一个接口。 这使得在单元测试中模拟attribute的实现变得容易起来。

8.3. 集成Jakarta Commons Attributes

虽然为其他元数据提供者来说,提供org.springframework.metadata.Attributes 接口的实现很简单,但是目前Spring只是直接支持Jakarta Commons Attributes。

Commons Attributes 2.0 (http://jakarta.apache.org/commons/sandbox/attributes/) 是一个功能很强的attribute解决方案。它支持通过构造函数参数和JavaBean属性来配置attribute, 也提供了更好的attribute定义的文档。(对JavaBean属性的支持是在Spring team的要求下添加的。)

我们已经看到了两个Commons Attributes的attribute定义的例子。通常,我们需要解释一下:

  • Attribute类的名称。 这可能是一个FQN,就像上面的那样。如果相关的attribute类已经被导入, 就不需要FQN了。你也可以在attibute编译器的设置中指定attribute的包名。

  • 任何必须的参数化,可以通过构造函数参数或者JavaBean属性完成。

Bean的属性如下:

/*** @@MyAttribute(myBooleanJavaBeanProperty=true)*/

把构造函数参数和JavaBean属性结合在一起也是可以的(就像在Spring IoC中一样)。

因为,并不象Java 1.5中的attribute一样,Common Attributes没有和Java语言本身结合起来, 因此需要运行一个特定的attribute编译的步骤作为整个构建过程的一部分。

为了在整个构建过程中运行Commmons Attributes,你需要做以下的事情。

1.复制一些必要的jar包到$ANT_HOME/lib目录下。 有四个必须的jar包,它们包含在Spring的发行包里:

  • Commons Attributes编译器的jar包和API的jar包。

  • 来自于XDoclet的xjavadoc.jar

  • 来自于Jakarta Commons的commons-collections.jar

2.把Commons Attributes的ant任务导入到你的项目构建脚本中去,如下:

<taskdef resource="org/apache/commons/attributes/anttasks.properties"/>

3.接下来,定义一个attribute编译任务,它将使用Commons Attributes的attribute-compiler任务 来“编译”源代码中的attribute。这个过程将生成额外的代码至destdir属性指定的位置。 在这里我们使用了一个临时目录:

<target name="compileAttributes" ><attribute-compiler destdir="${commons.attributes.tempdir}" ><fileset dir="${src.dir}" includes="**/*.java"/></attribute-compiler></target>

运行javac命令编译源代码的编译目标任务应该依赖于attribute编译任务,还需要编译attribute时生成至 目标临时目录的源代码。如果在attribute定义中有语法错误,通常都会被attribute编译器捕获到。 但是,如果attribute定义在语法上似是而非,却使用了一些非法的类型或类名, 编译所生成的attribute类可能会失败。在这种情况下,你可以看看所生成的类来确定错误的原因。

Commons Attributes也提供对Maven的支持。请参考Commons Attributes的文档得到进一步的信息。

虽然attribute编译的过程可能看起来复杂,实际上是一次性的耗费。一旦被创建后,attribute的编译是递增式的, 所以通常它不会减慢整个构建过程。一旦编译过程完成后, 你可能会发现本章中描述的attribute的使用将节省在其他方面的时间。

如果需要attribute的索引支持(目前只在Spring的以attribute为目标的web控制器中需要,下面会讨论到), 你需要一个额外的步骤,执行在包含编译后的类的jar文件上。在这步可选的步骤中, Commons Attributes将生成一个所有在你源代码中定义的attribute的索引,以便在运行时进行有效的查找。 该步骤如下:

<attribute-indexer jarFile="myCompiledSources.jar"><classpath refid="master-classpath"/></attribute-indexer>

可以到Spring jPetStore例程下的attributes目录下察看关于该构建过程的例子。 你可以使用它里面的构建脚本,并修改该脚本以适应你自己的项目。

如果你的单元测试依赖于attribute,尽量使它依赖于Spring对于Attribute的抽象,而不是Commons Attributes。 这不仅仅为了更好的移植性——举例来说,你的测试用例将来仍可以工作如果你转换至Java 1.5的attributes—— 它也简化了测试。Commons Attributes是静态的API,而Spring提供的是一个容易模拟的元数据接口。

8.4. 元数据和Spring AOP自动代理

元数据attributes最重要的用处是和Spring AOP的联合。 提供类似于.NET风格的编程模式,声明式的服务会被自动提供给声明了元数据attribute的应用对象。 这样的元数据attribute可以像在声明式事务管理一样被框架直接支持,也可以是自定义的.

这就是AOP和元数据attribute配合使用的优势所在。

8.4.1. 基础

基于Spring AOP自动代理功能实现。配置可能象这样:

<bean id="autoproxy" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
</bean><bean id="transactionAttributeSource"class="org.springframework.transaction.interceptor.AttributesTransactionAttributeSource"autowire="constructor">
</bean><bean id="transactionInterceptor"class="org.springframework.transaction.interceptor.TransactionInterceptor"autowire="byType">
</bean><bean id="transactionAdvisor"class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor"autowire="constructor" >
</bean><bean id="attributes"class="org.springframework.metadata.commons.CommonsAttributes"
/>

这里的基本概念和AOP章节中关于自动代理的讨论一致。

最重要的bean的定义名称为autoproxy和 transactionAdvisor。要注意bean的实际名称并不重要; 关键是它们的类。

所定义的自动代理bean org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator 将自动通知(“自动代理”)当前工厂类中的所有符合Advisor实现的bean实例, 这个类并不知道attribute,而是依赖符合的Advisors的切入点。这些切入点知道attribute的内容。

因而我们只是需要一个AOP的advisor来提供基于attribute的声明式事务管理。

也可以添加任意的自定义Advisor实现,它们将被自动计算并应用。 (如果有必要的话,你可以使用切入点除了符合自动代理配置的attribute,而且满足一定规则的Advisor。)

最后,attributes bean使用的是Commons Attributes的实现。 也可以用org.springframework.metadata.Attributes的另一个实现代替。

8.4.2. 声明式事务管理

源代码级的attribute的最普通用法是提供了类似.NET的声明式事务管理。一旦定义好上面的bean定义, 你就能定义任意数目的需要声明式事务的应用对象了。只有那些拥有事务attribute的类或方法会被有事务的通知。 除了定义你需要的事务attribute以外,其他什么都不用做。

不象在.NET中那样,你可以在类或方法级别指定事务attribute。 如果指定了类级别的attribute,它的所有方法都会“继承”它。 方法中定义的attribute将完全覆盖类上定义的attribute。

8.4.3. 缓冲池技术

再者,象.NET中一样,你可以通过在类上指定attribute增加缓冲池行为。 Spring能把该行为应用到任何普通Java对象上。你只需在需要缓冲的业务对象上指定一个缓冲池的attribute,如下:

 /** * @@org.springframework.aop.framework.autoproxy.target.PoolingAttribute (10)* * @author Rod Johnson*/
public class MyClass {

你需要通常的自动代理的基本配置。 然后指定一个支持缓冲池的TargetSourceCreator,如下所示。 由于缓冲池会影响目标对象的创建,我们不能使用一个通常的advice。 注意如果一个类有缓冲池的attribute,即使没有任何advisors应用到该类,缓冲池也会对该类起作用。

<bean id="poolingTargetSourceCreator"class="org.springframework.aop.framework.autoproxy.metadata.AttributesPoolingTargetSourceCreator"autowire="constructor" >
</bean>

对应的自动代理bean定义需要指定一系列的“自定义的目标源生成器”,包括支持缓冲池的目标源生成者。 我们可以修改上面的例子来引入这个属性,如下:

<bean id="autoproxy" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
><property name="customTargetSourceCreators"><list><ref local="poolingTargetSourceCreator" /></list></property>
</bean>

就像通常在Spring中使用元数据一样,这是一次性的耗费:一旦创建完成后, 在其它业务对象上使用缓冲池是非常容易的。

对于很少需要缓冲池技术的地方,很少需要缓冲大量业务对象,这是就值得斟酌了。 因此这个功能好像也不是经常使用。

详细请参考org.springframework.aop.framework.autoproxy包的Javadoc。 除了以最少的代码量使用Commons Pool以外,其它的缓冲池实现也是可以的。

8.4.4. 自定义的元数据

由于自动代理底层架构的灵活性,我们甚至还可以超越.NET元数据attribute的功能。

我们可以定义一些自定义的attribute来提供任何种类的行为。为了达到这个目的,你需要:

  • 定义你的自定义attribute类

  • 定义一个Spring AOP Advisor,自定义attributes的出现的时候触发它的切入点。

  • 把Advisor当作一个bean的定义添加到一个包含普通自动代理基础架构的应用上下文中。

  • 把attribute添加到普通Java对象上。

有几个潜在的领域中你可能想这么做,比如自定义的声明式安全管理,或者可能的缓存。

这是一个功能很强的机制,它能显著减少某些工程中的配置工作。但是,要记住它在底层是依赖AOP的。 你在应用的使用的Advisors越多,运行时配置将会越复杂。(如果你想查看object上应用了哪些通知, 可以看一下关于org.springframework.aop.framework.Advised的参考。它使你能够检查相关的Advisors。)

8.5. 使用attribute尽可能减少MVC web层配置

Spring 1.0中的元数据的另一个主要用法是为简化Spring MVC web配置提供了一个选择。

Spring MVC提供了灵活的处理器映射: 将外来的请求映射到控制器(或其它的处理器)实例上。 通常上处理器映射被配置在相应的Spring DispatcherServlet的xxx-servlet.xml文件中。

把这些配置定义在DispatcherServlet的配置文件中通常是个不错的选择。它提供了最大的灵活性。 特别的是:

  • Controller实例是显式的被Spring IoC通过XML bean定义来管理。

  • 该映射位于controller的外面, 所以相同controller的实例可以在同一个DispatcherServlet中被赋予不同的映射或者在不同的配置中重用。

  • Spring MVC能够支持在任何规则上的映射,而不是大多数其它框架中仅有的将请求URL映射到控制器。

然而,对于每个controller来说,我们同时需要一个处理器映射(通常是一个处理器映射的XML bean定义), 和一个控制器自身的一个XML映射描述。

Spring提供了一个基于源代码级attribute的更简单的方法,对于一些简单场景来说是一个吸引人的选择。

这一段描述的方法很适合一些简单的MVC场景。但它牺牲了一些Spring MVC的功能, 比如根据不同的映射使用相同的控制器,把映射基于除了请求的URL之外的规则。

在这种方法下,控制器上标记了一个或多个类级的元数据attribute, 每一个attribute指定了它们应该映射的一个URL。

下面的例子展示了这种方法。在每一种情况下,我们都有一个依赖于Cruncher类的业务对象控制器。 和往常一样,这种依赖性将通过依赖注射来解决。 Cruncher必须作为一个bean定义出现在相关的DispatcherServlet的XML文件中,或在一个父上下文中。

我们把一个attribute设置到控制器类上,并指定应该映射的URL。 我们可以通过JavaBean属性或构造函数参数来表达依赖关系。这种映射必须通过自动装配来解决: 那就是说,在上下文中必须只能有一个Crucher类型的业务对象。

/*** Normal comments here* @author Rod Johnson* @@org.springframework.web.servlet.handler.metadata.PathMap("/bar.cgi")*/
public class BarController extends AbstractController {private Cruncher cruncher;public void setCruncher(Cruncher cruncher) {this.cruncher = cruncher;}protected ModelAndView handleRequestInternal(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {System.out.println("Bar Crunching c and d =" + cruncher.concatenate("c", "d"));return new ModelAndView("test");}}

为了使这个自动映射起作用,我们需要添加下面的配置到相关的xxxx-servlet.xml文件中, 这些配置是用来指定相关attribute的处理器映射的。 这个特殊的处理器映射可以处理任意数量的象上面一样带有attribute的控制器。 Bean的id(“commonsAttributesHandlerMapping”)并不重要。关键是它的类型:

<bean id="commonsAttributesHandlerMapping"      class="org.springframework.web.servlet.handler.metadata.CommonsPathMapHandlerMapping"
/>

现在我们并不需要一个象上面例子中的Attributes bean的定义, 因为这个类直接利用Commons Attributes API,而不是通过Spring的元数据抽象。

现在我们不再需要对每一个控制器提供XML配置。控制器被自动映射到指定的URL上。 控制器得益于IoC,使用了Spring的自动装配功能。举例来说, 上述的简单控制器中的“cruncher”属性上的依赖性会自动在当前的web应用中解决. Setter方法和构造函数依赖注射都是可以的,每一个都是零配置。

构造函数注册的一个例子,同时演示了多个URL路径:

/**
* Normal comments here
* @author Rod Johnson
*
* @@org.springframework.web.servlet.handler.metadata.PathMap("/foo.cgi")
* @@org.springframework.web.servlet.handler.metadata.PathMap("/baz.cgi")
*/
public class FooController extends AbstractController {private Cruncher cruncher;public FooController(Cruncher cruncher) {this.cruncher = cruncher;}protected ModelAndView handleRequestInternal(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {return new ModelAndView("test");}}

这种方法有着下列的好处:

  • 显著的减少配置工作量。每一次我们增加一个控制器时,我们需要XML的配置。 就像attribute驱动的事务管理一样,一旦有了基础架构后,添加更多的应用类将会很简单。

  • 我们保留了Spring IoC配置控制器的能力。

不过该方法有如下的限制:

  • 这个方法使构建过程更加复杂,不过开销是一次性的。 我们需要一个attribute编译步骤和一个建立attribute的索引步骤。 但是,一旦这些步骤就位后,这将不再是一个问题。

  • 虽然将来会增加对其他attribute提供者的支持,但目前只支持Commons Attributes。

  • 只有“根据类型的自动装配”的依赖注射才支持这样的控制器。但是, 这妨碍这些控制器对Structs Actions(在框架中并没有IoC的支持), 和值得斟酌的WebWork Actions(只有基本的IoC支持,并且IoC逐步受到关注)的领先。

  • 依赖自动魔法的IoC解决方案可能是令人困惑的。

由于根据类型的自动装配意味着必须依赖一种指定类型,如果我们使用AOP就需要小心了。 在通常使用TransactionProxyFactoryBean的情况下,举例来说, 我们对一个业务接口例如Cruncher有两个实现: 一个为原始的普通Java对象的定义,另一个是带有事务的AOP代理。这将无法工作, 因为所有者应用上下文无法确切的解析这种类型依赖。解决方法是使用AOP的自动代理, 建立起自动代理的基本架构,这样就只有一个Crucher的实现, 同时该实现是自动被通知的。 因此这种方法和上面的以attribute为目标声明式服务能很好的一起工作。 因为attribute编译过程必须恰当处理web控制器的定位,所有这就很容易被创建

不象其它的元数据的功能,当前只有Commons Attributes的一种实现: org.springframework.web.servlet.handler.metadata.CommonsPathMapHandlerMapping。 这个限制是因为我们不仅需要attribute编译,还需要attribute索引: 根据attribute API来查询所有拥有PathMap attribute的类。虽然将来可能会提供, 但目前在org.springframework.metadata.Attributes的抽象接口上还没有提供索引。 (如果你需要增加另一个attribute实现的支持,并且必须支持索引, 你可以简单的继承AbstractPathMapHandlerMappingCommonsPathMapHandlerMapping的父类, 用你选择的attribute API来实现其中两个protected的虚方法。)

因此我们在构建过程中需要两个额外的步骤:attribute编译和建立attribute索引。 上面已经展示了attributer索引建立器的使用方法。要注意到目前Commons Attributes仍需要一个Jar文件来建立索引。

如果你开始使用控制器元数据映射方法,你可以在任何一个地方转换至经典的Spring XML映射方法。 所以你不需要拒绝这种选择。正因为这个原因,我发现我经常在开始一个web应用时使用元数据映射.

8.6. 元数据attribute的其它使用

对元数据attribute的其它应用看来正在流行。到2004年3月时, 一个为Spring建立的基于attribute的验证包正在开发中。 当考虑到潜在的多次使用时,attribute解析的一次性开销看起来更加吸引人了.

8.7. 增加对其它的元数据API的支持

如果你希望提供对另一种元数据API的支持,这是容易做到的。

简单的实现org.springframework.metadata.Attributes 接口作为你选择的元数据API的 外观(facade)。然后你就可以象上面那样把这个对象包括到你的bean定义中去。

所有使用元数据的框架服务,例如AOP元数据驱动的自动代理,将自动使用你的新元数据提供者。

我们期待着增加对Java 1.5的attribute的支持--可能作为Spring核心的附件--在2004年第二季度。


from: http://docs.huihoo.com/spring/zh-cn/metadata.html

Spring - Java/J2EE Application Framework 应用框架 第 8 章 源代码级的元数据支持相关推荐

  1. Spring - Java/J2EE Application Framework 应用框架 第 5 章 Spring AOP: Spring之面向方面编程G

    第 5 章 Spring AOP: Spring之面向方面编程 5.1. 概念 面向方面编程 (AOP) 提供从另一个角度来考虑程序结构以完善面向对象编程(OOP). 面向对象将应用程序分解成 各个层 ...

  2. Spring - Java/J2EE Application Framework 应用框架 第 5 章 Spring AOP: Spring之面向方面编程

    第 5 章 Spring AOP: Spring之面向方面编程 5.1. 概念 面向方面编程 (AOP) 提供从另一个角度来考虑程序结构以完善面向对象编程(OOP). 面向对象将应用程序分解成 各个层 ...

  3. Spring - Java/J2EE Application Framework 应用框架 第 1 章 简介

    第 1 章 简介 1.1. 概览 Spring包含许多功能和特性,并被很好地组织在下图所示的七个模块中.本节将依次介绍每个模块. Spring框架概览 Core包是框架的最基础部分, 并提供依赖注入( ...

  4. Spring - Java/J2EE Application Framework 应用框架 第 13 章 集成表现层

    第 13 章 集成表现层 13.1. 简介 Spring之所以出色的一个原因就是将表现层从MVC的框架中分离出来.例如,通过配置就可以让Velocity或者XSLT来代替已经存在的JSP页面.本章介绍 ...

  5. Spring - Java/J2EE Application Framework 应用框架 第 11 章 使用ORM工具进行数据访问

    第 11 章 使用ORM工具进行数据访问 11.1. 简介 Spring在资源管理,DAO实现支持以及实物策略等方面提供了与Hibernate, JDO和iBATIS SQL映射的集成. 对Hiber ...

  6. Spring - Java/J2EE Application Framework 应用框架 第 10 章 使用JDBC进行数据访问

    第 10 章 使用JDBC进行数据访问 10.1. 简介 Spring提供的JDBC抽象框架由core, datasource,object和support四个不同的包组成. 就和它名字的暗示一样,o ...

  7. Spring - Java/J2EE Application Framework 应用框架 第 7 章 事务管理

    第 7 章 事务管理 7.1. Spring事务抽象 Spring提供了一致的事务管理抽象.这个抽象是Spring最重要的抽象之一, 它有如下的优点: 为不同的事务API提供一致的编程模型,如JTA. ...

  8. Spring - Java/J2EE Application Framework 应用框架 第 14 章 JMS支持

    第 14 章 JMS支持 14.1. 介绍 Spring提供一个用于简化JMS API使用的抽象层框架,并且对用户屏蔽JMS API中从1.0.2到1.1版本之间的不同. JMS大体上被分为两个功能块 ...

  9. Spring - Java/J2EE Application Framework 应用框架 第 3 章 Beans, BeanFactory和ApplicationContext

    第 3 章 Beans, BeanFactory和ApplicationContext 3.1. 简介 在Spring中,两个最基本最重要的包是 org.springframework.beans 和 ...

最新文章

  1. linux selinux 安全上下文 修改
  2. 无意中发现一个有趣的事情
  3. visual studio2008 OpenGL开发配置
  4. Dotnet Core使用特定的SDKRuntime版本
  5. Cookie中不能有空格_前端小贴士 -- 全面了解Cookie
  6. Sigmatel37xx GPIO的使用
  7. (转)Javascript的DOM操作 - 性能优化
  8. 服务器文件权限在哪里,服务器中的文件权限设置在哪里
  9. Fiddler工具介绍一
  10. 神经网络算法的基本原理,神经网络算法都有哪些
  11. 2022-2027年中国血液制品行业市场深度分析及投资战略规划报告
  12. ERP: ERP系统的作用
  13. ubuntu下dbus工具d-feet不显示路径和接口
  14. JSjavascript获取B站bilibili哔哩哔哩分P播放列表并以excel文件保存本地
  15. 如何度过有用的每一天
  16. 自己制作脚手架——完整版
  17. PHP获取项目根目录
  18. 今日头条/字节跳动 后台开发岗(应届生)三轮技术面试
  19. 别把白内障拖成青光眼,不可逆的致盲眼病最可怕!
  20. PhotoshopCS5无法使用扫描仪的故障

热门文章

  1. ios 开发者账号申请流程 最新
  2. 【科技金融】专家评分卡和机器学习评分卡的差异化和必要性
  3. 中央纪委网站:​深度关注 | 元宇宙如何改写人类社会生活
  4. 若依项目linux部署
  5. YJango的循环神经网络——实现LSTM YJango的循环神经网络——实现LSTM YJango YJango 7 个月前 介绍 描述最常用的RNN实现方式:Long-Short Term Me
  6. https://wenku.baidu.com/view/1f9138e903d8ce2f01662306.html
  7. Regtech半月观察(9月上)
  8. mysql对数据库进行备份吗_怎么对MySQL数据库进行备份与恢复
  9. mysql什么情况会扫描所有_造成MySQL全表扫描的原因
  10. 腾讯面试题 linux下free命令详解