IoC容器和Dependency Injection模式.doc

Size: px
Start display at page:

Download "IoC容器和Dependency Injection模式.doc"

Transcription

1 IoC Dependency Injection 撰文 /Martin Fowler Java Inversion of Control IoC Dependency Injection Service Locator 在企业级 Java 的世界里存在一个有趣的现象 : 有很多人投入很多精力来研究主流 J2EE 技术的 替代品 自然, 这大多发生在 open source 社群 在很大程度上, 这可以看作是开发者对主 流 J2EE 技术的笨重和复杂作出的回应, 但其中的确有很多极富创意的想法, 的确提供了一些可 供选择的方案 J2EE 开发者常遇到的一个问题就是如何组装不同的程序元素 : 如果 web 控制 器体系结构和数据库接口是由不同的团队所开发的, 彼此几乎一无所知, 你应该如何让它们配合 工作? 很多框架尝试过解决这个问题, 有几个框架索性朝这个方向发展, 提供了更通用的 组装 各层组件 的方案 这样的框架通常被称为 轻量级容器, PicoContainer 和 Spring 都在此 列中 在这些容器背后, 一些有趣的设计原则发挥着作用 这些原则已经超越了特定容器的范畴, 甚至 已经超越了 Java 平台的范畴 在本文中, 我就要初步揭示这些原则 我使用的范例是 Java 代 码, 但正如我的大多数文章一样, 这些原则也同样适用于别的 OO 环境, 特别是.NET 装配程序元素, 这样的话题立即将我拖进了一个棘手的术语问题 : 如何区分 服务 ( service) 和 组件 ( component)? 你可以毫不费力地找出关于这两个词定义的长篇大论, 各种彼此矛盾的定义会让你感受到我所处的窘境 有鉴于此, 对于这两个遭到了严重滥用的词汇, 我将首先说明它们在本文中的用法 所谓 组件 是指这样一个软件单元 : 它将被作者无法控制的其他应用程序使用, 但后者不能对组件进行修改 也就是说, 使用一个组件的应用程序不能修改组件的源代码, 但可以通过作者预留的某种途径对其进行扩展, 以改变组件的行为 服务和组件有某种相似之处 : 它们都将被外部的应用程序使用 在我看来, 两者之间最大的差异在于 : 组件是在本地使用的 ( 例如 JAR 文件 程序集 DLL 或者源码导入); 而服务是要通过 同步或异步的 远程接口来远程使用的 ( 例如 web service 消息系统 RPC, 或者 socket) 在本文中, 我将主要使用 服务 这个词, 但文中的大多数逻辑也同样适用于本地组件 实际上, 为了方便地访问远程服务, 你往往需要某种本地组件框架 不过, 组件或者服务 这样一个词组实在太麻烦了, 而且 服务 这个词当下也很流行, 所以本文将用 服务 指代这两者

2 为了更好地说明问题, 我要引入一个例子 和我以前用的所有例子一样, 这是一个超级简单的例子 : 它非常小, 小得有点不够真实, 但足以帮助你看清其中的道理, 而不至于陷入真实例子的泥潭中无法自拔 在这个例子中, 我编写了一个组件, 用于提供一份电影清单, 清单上列出的影片都是由一位特定的导演执导的 实现这个伟大的功能只需要一个方法 : class MovieLister... public Movie[] moviesdirectedby(string arg) { List allmovies = finder.findall(); for (Iterator it = allmovies.iterator(); it.hasnext();) { Movie movie = (Movie) it.next(); if (!movie.getdirector().equals(arg)) it.remove(); return (Movie[]) allmovies.toarray(new Movie[allMovies.size()]); 你可以看到, 这个功能的实现极其简单 :moviesdirectedby 方法首先请求 finder( 影片搜寻者 ) 对象 ( 我们稍后会谈到这个对象 ) 返回后者所知道的所有影片, 然后遍历 finder 对象返回的清单, 并返回其中由特定的某个导演执导的影片 非常简单, 不过不必担心, 这只是整个例子的脚手架罢了 我们真正想要考察的是 finder 对象, 或者说, 如何将 MovieLister 对象与特定的 finder 对象连接起来 为什么我们对这个问题特别感兴趣? 因为我希望上面这个漂亮的 moviesdirectedby 方法完全不依赖于影片的实际存储方式 所以, 这个方法只能引用一个 finder 对象, 而 finder 对象则必须知道如何对 findall 方法作出回应 为了帮助读者更清楚地理解, 我给 finder 定义了一个接口 : public interface MovieFinder { List findall(); 现在, 两个对象之间没有什么耦合关系 但是, 当我要实际寻找影片时, 就必须涉及到 MovieFinder 的某个具体子类 在这里, 我把 涉及具体子类 的代码放在 MovieLister 类的构造子中 class MovieLister... private MovieFinder finder; public MovieLister() { finder = new ColonDelimitedMovieFinder("movies1.txt"); 这个实现类的名字就说明 : 我将要从一个逗号分隔的文本文件中获得影片列表 你不必操心具体的实现细节, 只要设想这样一个实现类就可以了 如果这个类只由我自己使用, 一切都没问题 但是, 如果我的朋友叹服于这个精彩的功能, 也想

3 使用我的程序, 那又会怎么样呢? 如果他们也把影片清单保存在一个逗号分隔的文本文件中, 并且也把这个文件命名为 movie1.txt, 那么一切还是没问题 如果他们只是给这个文件改改名, 我也可以从一个配置文件获得文件名, 这也很容易 但是, 如果他们用完全不同的方式 例如 SQL 数据库 XML 文件 web service, 或者另一种格式的文本文件 来存储影片清单呢? 在这种情况下, 我们需要用另一个类来获取数据 由于已经定义了 MovieFinder 接口, 我可以不用修改 moviesdirectedby 方法 但是, 我仍然需要通过某种途径获得合适的 MovieFinder 实现类的实例 图 1 展现了这种情况下的依赖关系 :MovieLister 类既依赖于 MovieFinder 接口, 也依赖于具体的实现类 我们当然希望 MovieLister 类只依赖于接口, 但我们要如何获得一个 MovieFinder 子类的实例呢? 在 Patterns of Enterprise Application Architecture 一书中, 我们把这种情况称为 插件 (plugin):moviefinder 的实现类不是在编译期连入程序之中的, 因为我并不知道我的朋友会使用哪个实现类 我们希望 MovieLister 类能够与 MovieFinder 的任何实现类配合工作, 并且允许在运行期插入具体的实现类, 插入动作完全脱离我 ( 原作者 ) 的控制 这里的问题就是 : 如何设计这个连接过程, 使 MovieLister 类在不知道实现类细节的前提下与其实例协同工作 将这个例子推而广之, 在一个真实的系统中, 我们可能有数十个服务和组件 在任何时候, 我们总可以对使用组件的情形加以抽象, 通过接口与具体的组件交流 ( 如果组件并没有设计一个接口, 也可以通过适配器与之交流 ) 但是, 如果我们希望以不同的方式部署这个系统, 就需要用插件机制来处理服务之间的交互过程, 这样我们才可能在不同的部署方案中使用不同的实现 所以, 现在的核心问题就是 : 如何将这些插件组合成一个应用程序? 这正是新生的轻量级容器所面临的主要问题, 而它们解决这个问题的手段无一例外地是控制反转 (Inversion of Control) 模式 几位轻量级容器的作者曾骄傲地对我说 : 这些容器非常有用, 因为它们实现了 控制反转 这样的说辞让我深感迷惑 : 控制反转是框架所共有的特征, 如果仅仅因为使用了控制反转就认为这些轻量级容器与众不同, 就好象在说 我的轿车是与众不同的, 因为它有四个轮子 问题的关键在于 : 它们反转了哪方面的控制? 我第一次接触到的控制反转针对的是用户界面的主控权 早期的用户界面是完全由应用程序来控制的, 你预先设计一系列命令, 例如 输入姓名

4 输入地址 等, 应用程序逐条输出提示信息, 并取回用户的响应 而在图形用户界面环境下, UI 框架将负责执行一个主循环, 你的应用程序只需为屏幕的各个区域提供事件处理函数即可 在这里, 程序的主控权发生了反转 : 从应用程序移到了框架 对于这些新生的容器, 它们反转的是 如何定位插件的具体实现 在前面那个简单的例子中, MovieLister 类负责定位 MovieFinder 的具体实现 它直接实例化后者的一个子类 这样一来,MovieFinder 也就不成其为一个插件了, 因为它并不是在运行期插入应用程序中的 而这些轻量级容器则使用了更为灵活的办法, 只要插件遵循一定的规则, 一个独立的组装模块就能够将插件的具体实现 注射 到应用程序中 因此, 我想我们需要给这个模式起一个更能说明其特点的名字 控制反转 这个名字太泛了, 常常让人有些迷惑 与多位 IoC 爱好者讨论之后, 我们决定将这个模式叫做 依赖注入 (Dependency Injection) 下面, 我将开始介绍 Dependency Injection 模式的几种不同形式 不过, 在此之前, 我要首先指出 : 要消除应用程序对插件实现的依赖, 依赖注入并不是唯一的选择, 你也可以用 Service Locator 模式获得同样的效果 介绍完 Dependency Injection 模式之后, 我也会谈到 Service Locator 模式 Dependency Injection 模式的基本思想是 : 用一个单独的对象 ( 装配器 ) 来获得 MovieFinder 的一个合适的实现, 并将其实例赋给 MovieLister 类的一个字段 这样一来, 我们就得到了图 2 所示的依赖图 : 依赖注入的形式主要有三种, 我分别将它们叫做构造子注入 (Constructor Injection ) 设值方法注入 (Setter Injection) 和接口注入 (Interface Injection) 如果读过最近关于 IoC 的一些讨论材料, 你不难看出 : 这三种注入形式分别就是 type 1 IoC ( 接口注入 ) type 2 IoC ( 设值方法注入 ) 和 type 3 IoC( 构造子注入 ) 我发现数字编号往往比较难记, 所以我使用了这里的命名方式

5 首先, 我要向读者展示如何用一个名为 PicoContainer 的轻量级容器完成依赖注入 之所以从这里开始, 主要是因为我在 ThoughtWorks 公司的几个同事在 PicoContainer 的开发社群中非常活跃 没错, 也可以说是某种偏袒吧 PicoContainer 通过构造子来判断 如何将 MovieFinder 实例注入 MovieLister 类 因此, MovieLister 类必须声明一个构造子, 并在其中包含所有需要注入的元素 : class MovieLister... public MovieLister(MovieFinder finder) { this.finder = finder; MovieFinder 实例本身也将由 PicoContainer 来管理, 因此文本文件的名字也可以由容器注入 : class ColonMovieFinder... public ColonMovieFinder(String filename) { this.filename = filename; 随后, 需要告诉 PicoContainer: 各个接口分别与哪个实现类关联 将哪个字符串注入 MovieFinder 组件 private MutablePicoContainer configurecontainer() { MutablePicoContainer pico = new DefaultPicoContainer(); Parameter[] finderparams = {new ConstantParameter("movies1.txt"); pico.registercomponentimplementation(moviefinder.class, ColonMovieFinder.class, finderparams); pico.registercomponentimplementation(movielister.class); return pico; 这段配置代码通常位于另一个类 对于我们这个例子, 使用我的 MovieLister 类的朋友需要在自己的设置类中编写合适的配置代码 当然, 还可以将这些配置信息放在一个单独的配置文件中, 这也是一种常见的做法 你可以编写一个类来读取配置文件, 然后对容器进行合适的设置 尽管 PicoContainer 本身并不包含这项功能, 但另一个与它关系紧密的项目 NanoContainer 提供了一些包装, 允许开发者使用 XML 配置文件保存配置信息 NanoContainer 能够解析 XML 文件, 并对底下的 PicoContainer 进行配置 这个项目的哲学观念就是 : 将配置文件的格式与底下的配置机制分离开 使用这个容器, 你写出的代码大概会是这样 : public void testwithpico() { MutablePicoContainer pico = configurecontainer(); MovieLister lister = (MovieLister) pico.getcomponentinstance(movielister.class); Movie[] movies = lister.moviesdirectedby("sergio Leone");

6 assertequals("once Upon a Time in the West", movies[0].gettitle()); 尽管在这里我使用了构造子注入, 实际上 PicoContainer 也支持设值方法注入, 不过该项目的 开发者更推荐使用构造子注入 Spring 框架是一个用途广泛的企业级 Java 开发框架, 其中包括了针对事务 持久化框架 web 应用开发和 JDBC 等常用功能的抽象 和 PicoContainer 一样, 它也同时支持构造子注入和设值方法注入, 但该项目的开发者更推荐使用设值方法注入 恰好适合这个例子 为了让 MovieLister 类接受注入, 我需要为它定义一个设值方法, 该方法接受类型为 MovieFinder 的参数 : class MovieLister... private MovieFinder finder; public void setfinder(moviefinder finder) { this.finder = finder; 类似地, 在 MovieFinder 的实现类中, 我也定义了一个设值方法, 接受类型为 String 的参数 : class ColonMovieFinder... public void setfilename(string filename) { this.filename = filename; 第三步是设定配置文件 Spring 支持多种配置方式, 你可以通过 XML 文件进行配置, 也可以直接在代码中配置 不过,XML 文件是比较理想的配置方式 <beans> <bean id="movielister" class="spring.movielister"> <property name="finder"> <ref local="moviefinder"/> </property> </bean> <bean id="moviefinder" class="spring.colonmoviefinder"> <property name="filename"> <value>movies1.txt</value> </property> </bean> </beans> 于是, 测试代码大概就像下面这样 : public void testwithspring() throws Exception { ApplicationContext ctx = new

7 FileSystemXmlApplicationContext("spring.xml"); MovieLister lister = (MovieLister) ctx.getbean("movielister"); Movie[] movies = lister.moviesdirectedby("sergio Leone"); assertequals("once Upon a Time in the West", movies[0].gettitle()); 除了前面两种注入技术, 还可以在接口中定义需要注入的信息, 并通过接口完成注入 Avalon 框架就使用了类似的技术 在这里, 我首先用简单的范例代码说明它的用法, 后面还会有更深入的讨论 首先, 我需要定义一个接口, 组件的注入将通过这个接口进行 在本例中, 这个接口的用途是将一个 MovieFinder 实例注入继承了该接口的对象 public interface InjectFinder { void injectfinder(moviefinder finder); 这个接口应该由提供 MovieFinder 接口的人一并提供 任何想要使用 MovieFinder 实例的类 ( 例如 MovieLister 类 ) 都必须实现这个接口 class MovieLister implements InjectFinder... public void injectfinder(moviefinder finder) { this.finder = finder; 然后, 我使用类似的方法将文件名注入 MovieFinder 的实现类 : public interface InjectFilename { void injectfilename (String filename); class ColonMovieFinder implements MovieFinder, InjectFilename... public void injectfilename(string filename) { this.filename = filename; 现在, 还需要用一些配置代码将所有的组件实现装配起来 简单起见, 我直接在代码中完成配置, 并将配置好的 MovieLister 对象保存在名为 lister 的字段中 : class IfaceTester... private MovieLister lister; private void configurelister() { ColonMovieFinder finder = new ColonMovieFinder(); finder.injectfilename("movies1.txt"); lister = new MovieLister(); lister.injectfinder(finder);

8 测试代码则可以直接使用这个字段 : class IfaceTester... public void testiface() { configurelister(); Movie[] movies = lister.moviesdirectedby("sergio Leone"); assertequals("once Upon a Time in the West", movies[0].gettitle()); Service Locator 依赖注入的最大好处在于 : 它消除了 MovieLister 类对具体 MovieFinder 实现类的依赖 这样一来, 我就可以把 MovieLister 类交给朋友, 让他们根据自己的环境插入一个合适的 MovieFinder 实现即可 不过,Dependency Injection 模式并不是打破这层依赖关系的唯一手段, 另一种方法是使用 Service Locator 模式 Service Locator 模式背后的基本思想是 : 有一个对象 ( 即服务定位器 ) 知道如何获得一个应用程序所需的所有服务 也就是说, 在我们的例子中, 服务定位器应该有一个方法, 用于获得一个 MovieFinder 实例 当然, 这不过是把麻烦换了一个样子, 我们仍然必须在 MovieLister 中获得服务定位器, 最终得到的依赖关系如图 3 所示 : 在这里, 我把 ServiceLocator 类实现为一个 Singleton 的注册表, 于是 MovieLister 就可以在实例化时通过 ServiceLocator 获得一个 MovieFinder 实例 class MovieLister... MovieFinder finder = ServiceLocator.movieFinder(); class ServiceLocator...

9 public static MovieFinder moviefinder() { return soleinstance.moviefinder; private static ServiceLocator soleinstance; private MovieFinder moviefinder; 和注入的方式一样, 我们也必须对服务定位器加以配置 在这里, 我直接在代码中进行配置, 但设计一种通过配置文件获得数据的机制也并非难事 class Tester... private void configure() { ServiceLocator.load(new ServiceLocator(new ColonMovieFinder("movies1.txt"))); class ServiceLocator... public static void load(servicelocator arg) { soleinstance = arg; public ServiceLocator(MovieFinder moviefinder) { this.moviefinder = moviefinder; 下面是测试代码 : class Tester... public void testsimple() { configure(); MovieLister lister = new MovieLister(); Movie[] movies = lister.moviesdirectedby("sergio Leone"); assertequals("once Upon a Time in the West", movies[0].gettitle()); 我时常听到这样的论调 : 这样的服务定位器不是什么好东西, 因为你无法替换它返回的服务实现, 从而导致无法对它们进行测试 当然, 如果你的设计很糟糕, 你的确会遇到这样的麻烦 ; 但你也可以选择良好的设计 在这个例子中,ServiceLocator 实例仅仅是一个简单的数据容器, 只需要对它做一些简单的修改, 就可以让它返回用于测试的服务实现 对于更复杂的情况, 我可以从 ServiceLocator 派生出多个子类, 并将子类型的实例传递给注册表的类变量 另外, 我可以修改 ServiceLocator 的静态方法, 使其调用 ServiceLocator 实例的方法, 而不是直接访问实例变量 我还可以使用特定于线程的存储机制, 从而提供特定于线程的服务定位器 所有这一切改进都无须修改 ServiceLocator 的使用者 一种改进的思路是 : 服务定位器仍然是一个注册表, 但不是 Singleton Singleton 的确是实现注册表的一种简单途径, 但这只是一个实现时的决定, 可以很轻松地改变它

10 上面这种简单的实现方式有一个问题 :MovieLister 类将依赖于整个 ServiceLocator 类, 但它需要使用的却只是后者所提供的一项服务 我们可以针对这项服务提供一个单独的接口, 减少 MovieLister 对 ServiceLocator 的依赖程度 这样一来,MovieLister 就不必使用整个的 ServiceLocator 接口, 只需声明它想要使用的那部分接口 此时,MovieLister 类的提供者也应该一并提供一个定位器接口, 使用者可以通过这个接口获得 MovieFinder 实例 public interface MovieFinderLocator { public MovieFinder moviefinder(); 真实的服务定位器需要实现上述接口, 提供访问 MovieFinder 实例的能力 : MovieFinderLocator locator = ServiceLocator.locator(); MovieFinder finder = locator.moviefinder(); public static ServiceLocator locator() { return soleinstance; public MovieFinder moviefinder() { return moviefinder; private static ServiceLocator soleinstance; private MovieFinder moviefinder; 你应该已经注意到了 : 由于想要使用接口, 我们不能再通过静态方法直接访问服务 我们必须首先通过 ServiceLocator 类获得定位器实例, 然后使用定位器实例得到我们想要的服务 上面是一个静态定位器的例子 对于你所需要的每项服务,ServiceLocator 类都有对应的方法 这并不是实现服务定位器的唯一方式, 你也可以创建一个动态服务定位器, 你可以在其中注册需要的任何服务, 并在运行期决定获得哪一项服务 在本例中,ServiceLocator 使用一个 map 来保存服务信息, 而不再是将这些信息保存在字段中 此外,ServiceLocator 还提供了一个通用的方法, 用于获取和加载服务对象 class ServiceLocator... private static ServiceLocator soleinstance; public static void load(servicelocator arg) { soleinstance = arg; private Map services = new HashMap(); public static Object getservice(string key){ return soleinstance.services.get(key); public void loadservice (String key, Object service) {

11 services.put(key, service); 同样需要对服务定位器进行配置, 将服务对象与适当的关键字加载到定位器中 : class Tester... private void configure() { ServiceLocator locator = new ServiceLocator(); locator.loadservice("moviefinder", new ColonMovieFinder("movies1.txt")); ServiceLocator.load(locator); 我使用与服务对象类名称相同的字符串作为服务对象的关键字 : class MovieLister... MovieFinder finder = (MovieFinder) ServiceLocator.getService("MovieFinder"); 总体而言, 我不喜欢这种方式 无疑, 这样实现的服务定位器具有更强的灵活性, 但它的使用方 式不够直观明朗 我只有通过文本形式的关键字才能找到一个服务对象 相比之下, 我更欣赏 通 过一个方法明确获得服务对象 的方式, 因为这让使用者能够从接口定义中清楚地知道如何获得 某项服务 Dependency Injection 和 Service Locator 两个模式并不是互斥的, 你可以同时使用它们, Avalon 框架就是这样的一个例子 Avalon 使用了服务定位器, 但 如何获得定位器 的信息则是通过注入的方式告知组件的 对于前面一直使用的例子,Berin Loritsch 发送给了我一个简单的 Avalon 实现版本 : public class MyMovieLister implements MovieLister, Serviceable { private MovieFinder finder; public void service( ServiceManager manager ) throws ServiceException { finder = (MovieFinder)manager.lookup("finder"); service 方法就是接口注入的例子, 它使容器可以将一个 ServiceManager 对象注入 MyMovieLister 对象 ServiceManager 则是一个服务定位器 在这个例子中,MyMovieLister 并不把 ServiceManager 对象保存在字段中, 而是马上借助它找到 MovieFinder 实例, 并将后者保存起来 到现在为止, 我一直在阐述自己对这两个模式 (Dependency Injection 模式和 Service

12 Locator 模式 ) 以及它们的变化形式的看法 现在, 我要开始讨论他们的优点和缺点, 以便指出 它们各自适用的场景 首先, 我们面临 Service Locator 和 Dependency Injection 之间的选择 应该注意, 尽管我们前面那个简单的例子不足以表现出来, 实际上这两个模式都提供了基本的解耦合能力 无论使用哪个模式, 应用程序代码都不依赖于服务接口的具体实现 两者之间最重要的区别在于 : 这个 具体实现 以什么方式提供给应用程序代码 使用 Service Locator 模式时, 应用程序代码直接向服务定位器发送一个消息, 明确要求服务的实现 ; 使用 Dependency Injection 模式时, 应用程序代码不发出显式的请求, 服务的实现自然会出现在应用程序代码中, 这也就是所谓 控制反转 控制反转是框架的共同特征, 但它也要求你付出一定的代价 : 它会增加理解的难度, 并且给调试带来一定的困难 所以, 整体来说, 除非必要, 否则我会尽量避免使用它 这并不意味着控制反转不好, 只是我认为在很多时候使用一个更为直观的方案 ( 例如 Service Locator 模式 ) 会比较合适 一个关键的区别在于 : 使用 Service Locator 模式时, 服务的使用者必须依赖于服务定位器 定位器可以隐藏使用者对服务具体实现的依赖, 但你必须首先看到定位器本身 所以, 问题的答案就很明朗了 : 选择 Service Locator 还是 Dependency Injection, 取决于 对定位器的依赖 是否会给你带来麻烦 Dependency Injection 模式可以帮助你看清组件之间的依赖关系 : 你只需观察依赖注入的机制 ( 例如构造子 ), 就可以掌握整个依赖关系 而使用 Service Locator 模式时, 你就必须在源代码中到处搜索对服务定位器的调用 具备全文检索能力的 IDE 可以略微简化这一工作, 但还是不如直接观察构造子或者设值方法来得轻松 这个选择主要取决于服务使用者的性质 如果你的应用程序中有很多不同的类要使用一个服务, 那么应用程序代码对服务定位器的依赖就不是什么大问题 在前面的例子中, 我要把 MovieLister 类交给朋友去用, 这种情况下使用服务定位器就很好 : 我的朋友们只需要对定位器做一点配置 ( 通过配置文件或者某些配置性的代码 ), 使其提供合适的服务实现就可以了 在这种情况下, 我看不出 Dependency Injection 模式提供的控制反转有什么吸引人的地方 但是, 如果把 MovieLister 看作一个组件, 要将它提供给别人写的应用程序去使用, 情况就不同了 在这种时候, 我无法预测使用者会使用什么样的服务定位器 API, 每个使用者都可能有自己的服务定位器, 而且彼此之间无法兼容 一种解决办法是为每项服务提供单独的接口, 使用者可以编写一个适配器, 让我的接口与他们的服务定位器相配合 但即便如此, 我仍然需要到第一个服务定位器中寻找我规定的接口 而且一旦用上了适配器, 服务定位器所提供的简单性就被大大削弱了 另一方面, 如果使用 Dependency Injection 模式, 组件与注入器之间不会有依赖关系, 因此组件无法从注入器那里获得更多的服务, 只能获得配置信息中所提供的那些 这也是 Dependency Injection 模式的局限性之一 人们倾向于使用 Dependency Injection 模式的一个常见理由是 : 它简化了测试工作 这里的关键是 : 出于测试的需要, 你必须能够轻松地在 真实的服务实现 与 供测试用的 伪 组件 之间切换 但是, 如果单从这个角度来考虑,Dependency Injection 模式和 Service Locator

13 模式其实并没有太大区别 : 两者都能够很好地支持 伪 组件的插入 之所以很多人有 Dependency Injection 模式更利于测试 的印象, 我猜是因为他们并没有努力保证服务定位器的可替换性 这正是持续测试起作用的地方 : 如果你不能轻松地用一些 伪 组件将一个服务架起来以便测试, 这就意味着你的设计出现了严重的问题 当然, 如果组件环境具有非常强的侵略性 ( 就像 EJB 框架那样 ), 测试的问题会更加严重 我的观点是 : 应该尽量减少这类框架对应用程序代码的影响, 特别是不要做任何可能使 编辑 - 执行 的循环变慢的事情 用插件 (plugin) 机制取代重量级组件会对测试过程有很大帮助, 这正是测试驱动开发 (Test Driven Development,TDD) 之类实践的关键所在 所以, 主要的问题在于 : 代码的作者是否希望自己编写的组件能够脱离自己的控制 被使用在另一个应用程序中 如果答案是肯定的, 那么他就不能对服务定位器做任何假设 哪怕最小的假设也会给使用者带来麻烦 在组合服务时, 你总得遵循一定的约定, 才可能将所有东西拼装起来 依赖注入的优点主要在于 : 它只需要非常简单的约定 至少对于构造子注入和设值方法注入来说是这样 相比于这两者, 接口注入的侵略性要强得多, 比起 Service Locator 模式的优势也不那么明显 所以, 如果你想要提供一个组件给多个使用者, 构造子注入和设值方法注入看起来很有吸引力 : 你不必在组件中加入什么希奇古怪的东西, 注入器可以相当轻松地把所有东西配置起来 设值函数注入和构造子注入之间的选择相当有趣, 因为它折射出面向对象编程的一些更普遍的问题 : 应该在哪里填充对象的字段, 构造子还是设值方法? 一直以来, 我首选的做法是尽量在构造阶段就创建完整 合法的对象 也就是说, 在构造子中填充对象字段 这样做的好处可以追溯到 Kent Beck 在 Smalltalk Best Practice Patterns 一书中介绍的两个模式 :Constructor Method 和 Constructor Parameter Method 带有参数的构造子可以明确地告诉你如何创建一个合法的对象 如果创建合法对象的方式不止一种, 你还可以提供多个构造子, 以说明不同的组合方式 构造子初始化的另一个好处是 : 你可以隐藏任何不可变的字段 只要不为它提供设值方法就行了 我认为这很重要 : 如果某个字段是不应该被改变的, 没有针对该字段的设值方法 就很清楚地说明了这一点 如果你通过设值方法完成初始化, 暴露出来的设值方法很可能成为你心头永远的痛 ( 实际上, 在这种时候我更愿意回避通常的设值方法约定, 而是使用诸如 initfoo 之类的方法名, 以表明该方法只应该在对象创建之初调用 ) 不过, 世事总有例外 如果参数太多, 构造子会显得凌乱不堪, 特别是对于不支持关键字参数的语言更是如此 的确, 如果构造子参数列表太长, 通常标志着对象太过繁忙, 理应将其拆分成几个对象, 但有些时候也确实需要那么多的参数 如果有不止一种的方式可以构造一个合法的对象, 也很难通过构造子描述这一信息, 因为构造子之间只能通过参数的个数和类型加以区分 这就是 Factory Method 模式适用的场合了, 工厂方法可以借助多个私有构造子和设值方法的组合来完成自己的任务 经典 Factory Method 模式的问题在于 : 它们往往以静态方法的形式出现, 你无法在接口中声明它们 你可以创建一个工厂类, 但那又变成另一个服务实体了 工厂服务 是一种不错的技巧, 但你仍然需要以某种方式实例化这个工厂对象, 问题仍然没有解决

14 如果要传入的参数是像字符串这样的简单类型, 构造子注入也会带来一些麻烦 使用设值方法注入时, 你可以在每个设值方法的名字中说明参数的用途 ; 而使用构造子注入时, 你只能靠参数的位置来决定每个参数的作用, 而记住参数的正确位置显然要困难得多 如果对象有多个构造子, 对象之间又存在继承关系, 事情就会变得特别讨厌 为了让所有东西都正确地初始化, 你必须将对子类构造子的调用转发给超类的构造子, 然后处理自己的参数 这可能造成构造子规模的进一步膨胀 尽管有这些缺陷, 但我仍然建议你首先考虑构造子注入 不过, 一旦前面提到的问题真的成了问题, 你就应该准备转为使用设值方法注入 在将 Dependecy Injection 模式作为框架的核心部分的几支团队之间, 构造子注入还是设值方法注入 引发了很多的争论 不过, 现在看来, 开发这些框架的大多数人都已经意识到 : 不管更喜欢哪种注入机制, 同时为两者提供支持都是有必要的 另一个问题相对独立, 但也经常与其他问题牵涉在一起 : 如何配置服务的组装, 通过配置文件还是直接编码组装? 对于大多数需要在多处部署的应用程序来说, 一个单独的配置文件会更合适 配置文件几乎都是 XML 文件,XML 也的确很适合这一用途 不过, 有些时候直接在程序代码中实现装配会更简单 譬如一个简单的应用程序, 也没有很多部署上的变化, 这时用几句代码来配置就比 XML 文件要清晰得多 与之相对的, 有时应用程序的组装非常复杂, 涉及大量的条件步骤 一旦编程语言中的配置逻辑开始变得复杂, 你就应该用一种合适的语言来描述配置信息, 使程序逻辑变得更清晰 然后, 你可以编写一个构造器 (builder) 类来完成装配工作 如果使用构造器的情景不止一种, 你可以提供多个构造器类, 然后通过一个简单的配置文件在它们之间选择 我常常发现, 人们太急于定义配置文件 编程语言通常会提供简捷而强大的配置管理机制, 现代编程语言也可以将程序编译成小的模块, 并将其插入大型系统中 如果编译过程会很费力, 脚本语言也可以在这方面提供帮助 通常认为, 配置文件不应该用编程语言来编写, 因为它们需要能够被不懂编程的系统管理人员编辑 但是, 这种情况出现的几率有多大呢? 我们真的希望不懂编程的系统管理人员来改变一个复杂的服务器端应用程序的事务隔离等级吗? 只有在非常简单的时候, 非编程语言的配置文件才有最好的效果 如果配置信息开始变得复杂, 就应该考虑选择一种合适的编程语言来编写配置文件 在 Java 世界里, 我们听到了来自配置文件的不和谐音 每个组件都有它自己的配置文件, 而且格式还各各不同 如果你要使用一打这样的组件, 你就得维护一打的配置文件, 那会很快让你烦死 在这里, 我的建议是 : 始终提供一种标准的配置方式, 使程序员能够通过同一个编程接口轻松地完成配置工作 至于其他的配置文件, 仅仅把它们当作一种可选的功能 借助这个编程接口, 开发者可以轻松地管理配置文件 如果你编写了一个组件, 则可以由组件的使用者来选择如何管理配置信息 : 使用你的编程接口 直接操作配置文件格式, 或者定义他们自己的配置文件格式, 并将其与你的编程接口相结合

15 所有这一切的关键在于 : 服务的配置应该与使用分开 实际上, 这是一个基本的设计原则 分离接口与实现 在面向对象程序里, 我们在一个地方用条件逻辑来决定具体实例化哪一个类, 以后的条件分支都由多态来实现, 而不是继续重复前面的条件逻辑, 这就是 分离接口与实现 的原则 如果对于一段代码而言, 接口与实现的分离还只是 有用 的话, 那么当你需要使用外部元素 ( 例如组件和服务 ) 时, 它就是生死攸关的大事 这里的第一个问题是 : 你是否希望将 选择具体实现类 的决策推迟到部署阶段 如果是, 那么你需要使用插入技术 使用了插入技术之后, 插件的装配原则上是与应用程序的其余部分分开的, 这样你就可以轻松地针对不同的部署替换不同的配置 这种配置机制可以通过服务定位器来实现 (Service Locator 模式 ), 也可以借助依赖注入直接完成 (Dependency Injection 模式 ) 在本文中, 我关注的焦点是使用 Dependency Injection 模式和 Service Locator 模式进行服务配置的基本问题 还有一些与之相关的话题值得关注, 但我已经没有时间继续申发下去了 特别值得注意的是生命周期行为的问题 : 某些组件具有特定的生命周期事件, 例如 停止 开始 等等 另一个值得注意的问题是 : 越来越多的人对 如何在这些容器中运用面向方面 (aspect oriented) 的思想 产生了兴趣 尽管目前还没有认真准备过这方面的材料, 但我也很希望以后能在这个话题上写一些东西 关于这些问题, 你在专注于轻量级容器的网站上可以找到很多资料 浏览 PicoContainer ( 或者 Spring( 的网站, 你可以找到大量相关的讨论, 并由此引申出更多的话题 在时下流行的轻量级容器都使用了一个共同的模式来组装应用程序所需的服务, 我把这个模式称为 Dependency Injection, 它可以有效地替代 Service Locator 模式 在开发应用程序时, 两者不相上下, 但我认为 Service Locator 模式略有优势, 因为它的行为方式更为直观 但是, 如果你开发的组件要交给多个应用程序去使用, 那么 Dependency Injection 模式会是更好的选择 如果你决定使用 Dependency Injection 模式, 这里还有几种不同的风格可供选择 我建议你首先考虑构造子注入 ; 如果遇到了某些特定的问题, 再改用设值方法注入 如果你要选择一个容器, 在其之上进行开发, 我建议你选择同时支持这两种注入方式的容器 Service Locator 模式和 Dependency Injection 模式之间的选择并是最重要的, 更重要的是 : 应该将服务的配置和应用程序内部对服务的使用分离开 在此, 我要向帮助我理解本文中所提到的问题 并对本文提出宝贵意见的几个人表示感谢, 他们 是 Rod Johnson Paul Hammant Joe Walnes Aslak Hellesoy Jon Tirsen 和 Bill Caputo

16 另外,Berin Loritsch 和 Hamilton Verissimo de Oliveira 在 Avalon 方面给了我非常有用的 建议, 一并向他们表示感谢

IoC容器和Dependency Injection模式.doc

IoC容器和Dependency Injection模式.doc IoC Dependency Injection /Martin Fowler / Java Inversion of Control IoC Dependency Injection Service Locator Java J2EE open source J2EE J2EE web PicoContainer Spring Java Java OO.NET service component

More information

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double

More information

EJB-Programming-3.PDF

EJB-Programming-3.PDF :, JBuilder EJB 2.x CMP EJB Relationships JBuilder EJB Test Client EJB EJB Seminar CMP Entity Beans Value Object Design Pattern J2EE Design Patterns Value Object Value Object Factory J2EE EJB Test Client

More information

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP: ******************* * 关于 Java 测试试题 ******

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP:  ******************* * 关于 Java 测试试题 ****** ******************* * 关于 Java 测试试题 ******************* 問 1 运行下面的程序, 选出一个正确的运行结果 public class Sample { public static void main(string[] args) { int[] test = { 1, 2, 3, 4, 5 ; for(int i = 1 ; i System.out.print(test[i]);

More information

Spring3.x开发入门

Spring3.x开发入门 Spring Bean 管理 Spring 的工厂类 课程安排 Spring 的 Bean 管理 (XML 方式 ) Spring 的属性注入 (XML 方式 ) Spring 的 Bean 管理 ( 注解方式 ) Spring 的属性注入 ( 注解方式 ) Spring 的工厂类 Spring 的 Bean 管理 (XML 方式 ) 三种实例化 Bean 的方式 使用类构造器实例化 ( 默认无参数

More information

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double x) { d

More information

EJB-Programming-4-cn.doc

EJB-Programming-4-cn.doc EJB (4) : (Entity Bean Value Object ) JBuilder EJB 2.x CMP EJB Relationships JBuilder EJB Test Client EJB EJB Seminar CMP Entity Beans Session Bean J2EE Session Façade Design Pattern Session Bean Session

More information

本章学习目标 小风 Java 实战系列教程 SpringMVC 简介 SpringMVC 的入门案例 SpringMVC 流程分析 配置注解映射器和适配器 注解的使用 使用不同方式的跳转页面 1. SpringMVC 简介 Spring web mvc

本章学习目标 小风 Java 实战系列教程 SpringMVC 简介 SpringMVC 的入门案例 SpringMVC 流程分析 配置注解映射器和适配器 注解的使用 使用不同方式的跳转页面 1. SpringMVC 简介 Spring web mvc 本章学习目标 SpringMVC 简介 SpringMVC 的入门案例 SpringMVC 流程分析 配置注解映射器和适配器 配置视图解析器 @RequestMapping 注解的使用 使用不同方式的跳转页面 1. SpringMVC 简介 Spring web mvc 和 Struts2 都属于表现层的框架, 它是 Spring 框架的一部分, 我们可 以从 Spring 的整体结构中看得出来 :

More information

IDEO_HCD_0716

IDEO_HCD_0716 IDEO HCD Toolkit Tencent CDC ...? Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC

More information

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例 帝国 CMS 下在 PHP 文件中调用数据库类执行 SQL 语句实例 这篇文章主要介绍了帝国 CMS 下在 PHP 文件中调用数据库类执行 SQL 语句实例, 本文还详细介绍了帝国 CMS 数据库类中的一些常用方法, 需要的朋友可以参考下 例 1: 连接 MYSQL 数据库例子 (a.php)

More information

untitled

untitled 4.1AOP AOP Aspect-oriented programming AOP 來說 AOP 令 理 Cross-cutting concerns Aspect Weave 理 Spring AOP 來 AOP 念 4.1.1 理 AOP AOP 見 例 來 例 錄 Logging 錄 便 來 例 行 留 錄 import java.util.logging.*; public class HelloSpeaker

More information

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 odps-sdk 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基 开放数据处理服务 ODPS SDK SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基础功能的主体接口, 搜索关键词 "odpssdk-core" 一些

More information

在Spring中使用Kafka:Producer篇

在Spring中使用Kafka:Producer篇 在某些情况下, 我们可能会在 Spring 中将一些 WEB 上的信息发送到 Kafka 中, 这时候我们就需要在 Spring 中编写 Producer 相关的代码了 ; 不过高兴的是,Spring 本身提供了操作 Kafka 的相关类库, 我们可以直接通过 xml 文件配置然后直接在后端的代码中使用 Kafka, 非常地方便 本文将介绍如果在 Spring 中将消息发送到 Kafka 在这之前,

More information

工程项目进度管理 西北工业大学管理学院 黄柯鑫博士 甘特图 A B C D E F G 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 甘特图的优点 : 直观明了 ( 图形化概要 ); 简单易懂 ( 易于理解 ); 应用广泛 ( 技术通用 ) 甘特图的缺点 : 不能清晰表示活动间的逻辑关系 WBS 责任分配矩阵 ( 负责〇审批

More information

李 琼 评扎迪 史密斯的 白牙 要是他 指艾伯特 加勒比海移民 真的回去 了 那么他将要面临的失败是明摆在那儿的 因为当地并没有发生什么变化 这就是移民的悲剧 他们比他们离弃的故乡变化得更 快 于是他们永远也不可能因回到家乡而感 到幸福 可是 他们在移居的国家也不幸福 因为这不是家乡 瞿世镜

李 琼 评扎迪 史密斯的 白牙 要是他 指艾伯特 加勒比海移民 真的回去 了 那么他将要面临的失败是明摆在那儿的 因为当地并没有发生什么变化 这就是移民的悲剧 他们比他们离弃的故乡变化得更 快 于是他们永远也不可能因回到家乡而感 到幸福 可是 他们在移居的国家也不幸福 因为这不是家乡 瞿世镜 略论英国移民族群认同的发展和走向 李 琼 李 琼 评扎迪 史密斯的 白牙 要是他 指艾伯特 加勒比海移民 真的回去 了 那么他将要面临的失败是明摆在那儿的 因为当地并没有发生什么变化 这就是移民的悲剧 他们比他们离弃的故乡变化得更 快 于是他们永远也不可能因回到家乡而感 到幸福 可是 他们在移居的国家也不幸福 因为这不是家乡 瞿世镜 年 外国文学 第 期 这些天来 我觉得来到这个国家 就像是和魔鬼签了协议

More information

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1 C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 月 3 日 1 1 INPUTOUTPUT 1 InputOutput 题目描述 用 cin 输入你的姓名 ( 没有空格 ) 和年龄 ( 整数 ), 并用 cout 输出 输入输出符合以下范例 输入 master 999 输出 I am master, 999 years old. 注意 "," 后面有一个空格,"." 结束,

More information

软件工程文档编制

软件工程文档编制 实训抽象类 一 实训目标 掌握抽象类的定义 使用 掌握运行时多态 二 知识点 抽象类的语法格式如下 : public abstract class ClassName abstract void 方法名称 ( 参数 ); // 非抽象方法的实现代码 在使用抽象类时需要注意如下几点 : 1 抽象类不能被实例化, 实例化的工作应该交由它的子类来完成 2 抽象方法必须由子类来进行重写 3 只要包含一个抽象方法的抽象类,

More information

Microsoft Word - 新1-12.doc

Microsoft Word - 新1-12.doc 实训 5 面向对象编程练习 实训 5 面向对象编程练习 5.1 实训目的 通过编程和上机实验理解 Java 语言是如何体现面向对象编程基本思想 以及如何创建类 和对象 了解成员变量和成员方法的特性 5.2 实训要求 编写一个体现面向对象思想的程序 编写一个创建对象和使用对象的方法的程序 5.3 实训内容 5.3.1 创建对象并使用对象 1 定义一个 Person 类 可以在应用程序中使用该类 成员属性

More information

ESOL-CN-Bleed.pub

ESOL-CN-Bleed.pub NZCB Discover New Zealand BELIEVE YOU CAN www.nzcb.ac.nz ,, 我非常喜欢这里, 我在这里得到了很多的帮助, 谢谢学校为我提供这么好的学习环境和升学机会, 因此我也强烈推荐我的朋友们也来 NZCB 学习国际英文 (IESOL) 课程 - 黎曦 ( 中国 ) 在 NZCB 学习期间我的收获非常大, 不止是英语能力的提升, 还让我更加熟悉新西兰,

More information

无类继承.key

无类继承.key 无类继承 JavaScript 面向对象的根基 周爱 民 / aimingoo aiming@gmail.com https://aimingoo.github.io https://github.com/aimingoo rand = new Person("Rand McKinnon",... https://docs.oracle.com/cd/e19957-01/816-6408-10/object.htm#1193255

More information

PowerPoint 演示文稿

PowerPoint 演示文稿 The BitCoin Scripting Language 交易实例 交易结构 "result": { "txid": "921a dd24", "hash": "921a dd24", "version": 1, "size": 226, "locktime": 0, "vin": [ ], "vout": [ ], "blockhash": "0000000000000000002c510d

More information

JBuilder Weblogic

JBuilder Weblogic JUnit ( bliu76@yeah.net) < >6 JUnit Java Erich Gamma Kent Beck JUnit JUnit 1 JUnit 1.1 JUnit JUnit java XUnit JUnit 1.2 JUnit JUnit Erich Gamma Kent Beck Erich Gamma Kent Beck XP Extreme Programming CRC

More information

欢迎访问动力节点官方网站,动力节点java0基础免费学习半个月,java就业班免费学习一个月,满意后再交学费,请稊等,正在为您接入咨询老师

欢迎访问动力节点官方网站,动力节点java0基础免费学习半个月,java就业班免费学习一个月,满意后再交学费,请稊等,正在为您接入咨询老师 JDK 中的设计模式应用实例在 JDK(Java Development Kit) 类库中, 开发人员使用了大量设计模式, 正因为如此, 我们可以在不修改 JDK 源码的前提下开发出自己的应用软件, 本文列出了部分 JDK 中的模式应用实例, 有兴趣的同学可以深入研究, 看看前 Sun 公司的开发人员是如何在实际框架开发中运用设计模式的,Sunny 认为, 研究 JDK 类库中的模式实例也不失为学习如何使用设计模式的一个好方式.

More information

骨头的故事

骨头的故事 头 1 图 206 33 7 12 5 5 4 12 2 54 10 200-400 3 500 图 类 图 图 动 节 4 5 图 发 图 节 180 Youtube 180 [1] 7 2 7 6 9 270 6 图 树懒 块颈 13-25 14 17 25 7 图 扭头 头鹰 鹅 8 图 红 为 关节 绿 为 关节 9 图 类 10 图 类 11 图 盘 动 类 图 阴 犸 艺 你可能会以为图

More information

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入 100 年 特 種 考 試 地 方 政 府 公 務 人 員 考 試 試 題 等 別 : 三 等 考 試 類 科 : 資 訊 處 理 科 目 : 系 統 分 析 與 設 計 一 請 參 考 下 列 旅 館 管 理 系 統 的 使 用 案 例 圖 (Use Case Diagram) 撰 寫 預 約 房 間 的 使 用 案 例 規 格 書 (Use Case Specification), 繪 出 入

More information

Guava学习之Resources

Guava学习之Resources Resources 提供提供操作 classpath 路径下所有资源的方法 除非另有说明, 否则类中所有方法的参数都不能为 null 虽然有些方法的参数是 URL 类型的, 但是这些方法实现通常不是以 HTTP 完成的 ; 同时这些资源也非 classpath 路径下的 下面两个函数都是根据资源的名称得到其绝对路径, 从函数里面可以看出,Resources 类中的 getresource 函数都是基于

More information

“百企入校——广西青年企业家协会高校

“百企入校——广西青年企业家协会高校 百 企 入 校 广 西 青 年 企 业 家 协 会 高 校 毕 业 生 就 业 专 场 招 聘 会 信 息 简 介 时 间 :2016 年 6 月 12 日 9:00 14:00 地 点 : 广 西 财 经 学 院 明 秀 校 区 东 区 篮 球 场 ( 南 宁 市 西 乡 塘 区 明 秀 西 路 100 号 ) 面 向 对 象 : 1.2016 届 高 校 毕 业 生 往 届 毕 业 生 2. 服

More information

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课 复习 Java 包 创建包 : package 语句, 包结构与目录结构一致 使用包 : import restaurant/ - people/ - Cook.class - Waiter.class - tools/ - Fork.class

More information

¼ ½ ¾ ¼ ½ ¾

¼ ½ ¾ ¼ ½ ¾ 回归传统 历史学视野中的资本主义 刘光临 虽然明清资本主义萌芽研究和西方现代史学都使用了资本主义一词 但双方并无相同的理论背景 资本主义作为一个成熟的学科概念是由 世纪末 世纪初的历史学家和强调历史面向的政治经济学家 可简称为 德国历史学派 一起创造出来的 强调从历史而不是从抽象的理论中寻求社会变化的原因 资本主义萌芽这一概念的启用 实际上是对欧洲近代历史的严重误读 有鉴于此 在今后的中国历史研究中应该用资本主义来取代资本主义萌芽

More information

基于CDIO一体化理念的课程教学大纲设计

基于CDIO一体化理念的课程教学大纲设计 Java 语 言 程 序 设 计 课 程 教 学 大 纲 Java 语 言 程 序 设 计 课 程 教 学 大 纲 一 课 程 基 本 信 息 1. 课 程 代 码 :52001CC022 2. 课 程 名 称 :Java 语 言 程 序 设 计 3. 课 程 英 文 名 称 :Java Programming 4. 课 程 类 别 : 理 论 课 ( 含 实 验 上 机 或 实 践 ) 5. 授

More information

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 ->

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 -> 目录 1 大概思路... 1 2 创建 WebAPI... 1 3 创建 CrossMainController 并编写... 1 4 Nuget 安装 microsoft.aspnet.webapi.cors... 4 5 跨域设置路由... 4 6 编写 Jquery EasyUI 界面... 5 7 运行效果... 7 8 总结... 7 1 1 大概思路 创建 WebAPI 创建 CrossMainController

More information

2. AOP 底层技术实现 小风 Java 实战系列教程 关键词 : 代理模式 代理模型分为两种 : 1) 接口代理 (JDK 动态代理 ) 2) 子类代理 (Cglib 子类代理 ) 需求 :CustomerService 业务类, 有 save,update 方法, 希望在 save,updat

2. AOP 底层技术实现 小风 Java 实战系列教程 关键词 : 代理模式 代理模型分为两种 : 1) 接口代理 (JDK 动态代理 ) 2) 子类代理 (Cglib 子类代理 ) 需求 :CustomerService 业务类, 有 save,update 方法, 希望在 save,updat 本章学习目标 小风 Java 实战系列教程 AOP 思想概述 AOP 底层技术实现 AOP 术语介绍 SpringAOP 的 XML 方式 HelloWorld SpringAOP 的 XML 方式配置细节 SpringAOP 的注解方式 SpringAOP 的零配置方式 1. AOP 思想概述 1.1. AOP 思想简介 1.2. AOP 的作用 2. AOP 底层技术实现 小风 Java 实战系列教程

More information

大连软~1

大连软~1 大 连 软 件 职 业 学 院 高 等 职 业 教 育 质 量 年 度 报 告 ( ) 二 〇 一 六 年 一 月 ( 二 学 2...4 大 连 软 件 职 业 学 院 高 等 职 业 教 育 质 量 报 告 (2015)...4 目 录 一 学 院 基 本 情 况 二 办 学 基 本 信...8...6...7 息 ( 一 ) 明 确 办 学 思 路, 科 学 谋 划 发 展 战 略 ( 二 )

More information

一 登录 crm Mobile 系统 : 输入 ShijiCare 用户名和密码, 登录系统, 如图所示 : 第 2 页共 32 页

一 登录 crm Mobile 系统 : 输入 ShijiCare 用户名和密码, 登录系统, 如图所示 : 第 2 页共 32 页 第 1 页共 32 页 crm Mobile V1.0 for IOS 用户手册 一 登录 crm Mobile 系统 : 输入 ShijiCare 用户名和密码, 登录系统, 如图所示 : 第 2 页共 32 页 二 crm Mobile 界面介绍 : 第 3 页共 32 页 三 新建 (New) 功能使用说明 1 选择产品 第 4 页共 32 页 2 填写问题的简要描述和详细描述 第 5 页共

More information

untitled

untitled JavaEE+Android - 6 1.5-2 JavaEE web MIS OA ERP BOSS Android Android Google Map office HTML CSS,java Android + SQL Sever JavaWeb JavaScript/AJAX jquery Java Oracle SSH SSH EJB+JBOSS Android + 1. 2. IDE

More information

<4D6963726F736F667420506F776572506F696E74202D20C8EDBCFEBCDCB9B9CAA6D1D0D0DEBDB2D7F92E707074>

<4D6963726F736F667420506F776572506F696E74202D20C8EDBCFEBCDCB9B9CAA6D1D0D0DEBDB2D7F92E707074> 软 件 架 构 师 研 修 讲 座 胡 协 刚 软 件 架 构 师 UML/RUP 专 家 szjinco@public.szptt.net.cn 中 国 软 件 架 构 师 网 东 软 培 训 中 心 小 故 事 : 七 人 分 粥 当 前 软 件 团 队 的 开 发 现 状 和 面 临 的 问 题 软 件 项 目 的 特 点 解 决 之 道 : 从 瀑 布 模 型 到 迭 代 模 型 解 决 项

More information

untitled

untitled -JAVA 1. Java IDC 20 20% 5 2005 42.5 JAVA IDC JAVA 60% 70% JAVA 3 5 10 JAVA JAVA JAVA J2EE J2SE J2ME 70% JAVA JAVA 20 1 51 2. JAVA SUN JAVA J2EE J2EE 3. 1. CSTP CSTP 2 51 2. 3. CSTP IT CSTP IT IT CSTP

More information

器之 间 向一致时为正 相反时则为负 ③大量电荷的定向移动形成电 流 单个电荷的定向移动同样形成电流 3 电势与电势差 1 陈述概念 电场中某点处 电荷的电势能 E p 与电荷量 q Ep 的比值叫做该点处的电势 表达式为 V 电场中两点之间的 q 电势之差叫做电势差 表达式为 UAB V A VB 2 理解概念 电势差是电场中任意两点之间的电势之差 与参考点的选择无关 电势是反映电场能的性质的物理量

More information

untitled

untitled rxli@public.wh.hb.cn http://idc.hust.edu.cn/~rxli/ 2 3 ( ) (Distributed System) Integrated System () 4 5 6 System Integration 7 8 Integrated System 9 1.1 CIMS IDEF CSCW STEP MIS MRPII ERP CRM SCM MIS:

More information

(, : )?,,,,, (, : ),,,, (, ;, ;, : ),,, (, : - ),,, (, : ),,,,,,,,,,,,, -,,,, -,,,, -,,,,,,, ( ), ;, ( ) -,,,,,,

(, : )?,,,,, (, : ),,,, (, ;, ;, : ),,, (, : - ),,, (, : ),,,,,,,,,,,,, -,,,, -,,,, -,,,,,,, ( ), ;, ( ) -,,,,,, : 曹正汉 :, '.,,,., -..,.,,,.,, -., -,,,,,,,,,,,,,,, ( ),,,,,,,?,,?,, ( ), :? (. ) (, ),?, (, : )?,,,,, (, : ),,,, (, ;, ;, : ),,, (, : - ),,, (, : ),,,,,,,,,,,,, -,,,, -,,,, -,,,,,,, ( ), ;, ( ) -,,,,,,

More information

声 明 本 公 司 及 全 体 董 事 监 事 高 级 管 理 人 员 承 诺 不 存 在 虚 假 记 载 误 导 性 陈 述 或 重 大 遗 漏, 并 对 其 真 实 性 准 确 性 完 整 性 承 担 个 别 和 连 带 的 法 律 责 任 本 公 司 负 责 人 和 主 管 会 计 工 作 的

声 明 本 公 司 及 全 体 董 事 监 事 高 级 管 理 人 员 承 诺 不 存 在 虚 假 记 载 误 导 性 陈 述 或 重 大 遗 漏, 并 对 其 真 实 性 准 确 性 完 整 性 承 担 个 别 和 连 带 的 法 律 责 任 本 公 司 负 责 人 和 主 管 会 计 工 作 的 ( 申 报 稿 ) 主 办 券 商 二 零 一 五 年 七 月 声 明 本 公 司 及 全 体 董 事 监 事 高 级 管 理 人 员 承 诺 不 存 在 虚 假 记 载 误 导 性 陈 述 或 重 大 遗 漏, 并 对 其 真 实 性 准 确 性 完 整 性 承 担 个 别 和 连 带 的 法 律 责 任 本 公 司 负 责 人 和 主 管 会 计 工 作 的 负 责 人 会 计 机 构 负 责

More information

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 5 月 2 日晚 9 点 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double x) { d =

More information

res/layout 目录下的 main.xml 源码 : <?xml version="1.0" encoding="utf 8"?> <TabHost android:layout_height="fill_parent" xml

res/layout 目录下的 main.xml 源码 : <?xml version=1.0 encoding=utf 8?> <TabHost android:layout_height=fill_parent xml 拓展训练 1- 界面布局 1. 界面布局的重要性做应用程序, 界面是最基本的 Andorid 的界面, 需要写在 res/layout 的 xml 里面, 一般情况下一个 xml 对应一个界面 Android 界面布局有点像写 html( 连注释代码的方式都一样 ), 要先给 Android 定框架, 然后再在框架里面放控件,Android 提供了几种框架,AbsoluteLayout,LinearLayout,

More information

关于罗斯福时代新政 宪法革命 的几点浅见 韩 铁 美国宪法的若干重要法理原则及其运用在富兰克林 罗斯福总统任内 发生了巨大变化 史称新政 宪法革命 不过 这种变化并不是在所谓 年最高法院的 及时转向 中一锤定音的 最高法院在正当程序 商业权 公众福利条款上的态度及其变化充分说明 新政宪法革命无论是从当时还是其后的发展来看都有它的连续性 局限性和复杂性 只有认识到了这一点 我们对新政宪法革命乃至于整个新政的历史评价才会比较准确

More information

Stateless Session Beans(无状态bean)的学习

Stateless Session Beans(无状态bean)的学习 一 Stateless Session Beans( 无状态 bean) 的学习 第一步 : 要定义一个会话 Bean, 首先需要定义一个包含他所有业务方法的接口 这个接口不需要任何注释, 就像普通的 java 接口那样定义 调用 EJB 的客户端通过使用这个接口引用从 EJB 容器得到的会话 Bean 对象 stub 接口的定义如下: HelloWorld.java package com.foshanshop.ejb3;

More information

论文,,, ( &, ), 1 ( -, : - ), ; (, ), ; ;, ( &, ),,,,,, (, ),,,, (, ) (, ),,, :. : ( ), ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ), ( ),,,, 1 原译作 修补者, 但在英译版本中, 被译作

论文,,, ( &, ), 1 ( -, : - ), ; (, ), ; ;, ( &, ),,,,,, (, ),,,, (, ) (, ),,, :. : ( ), ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ), ( ),,,, 1 原译作 修补者, 但在英译版本中, 被译作 * 夏传玲 : 本文简要回顾了国内外定性研究在最近 多年的发展概况, 总结 了定性研究的六个发展趋势和分析策略上的三种流派 在上述两种背景下, 本文探讨了计算机辅助的定性分析给定性研究带来的机遇和挑战, 特别是它和手工操作对比时的优势和劣势, 以及应用这种定性分析技术所可能面临的困难 : 定性研究定性分析 文化差异,, (, ),,,, ( - ) ( - ) ( - ) ( - ) ( - ) (

More information

J2ME ISBN J2ME MIDP MIDP 2.0 API J2ME Netbeans IDE 4.1 Mobility Pack 4.1 MIDlet MIDlet MIDP PUSH API PDA API Ja

J2ME ISBN J2ME MIDP MIDP 2.0 API J2ME Netbeans IDE 4.1 Mobility Pack 4.1 MIDlet MIDlet MIDP PUSH API PDA API Ja Java JBuilder 2005 2005 6 ISBN 7-121-01166-2 69.00 1 688 JBuilder JBuilder 2005 JBuilder JBuilder 2005 JBuilder 2005 Java Java Java JBuilder 17 J2ME 2006 1 ISBN 7-121-02210-9 39.00 1 436 J2ME MIDP MIDP

More information

信息

信息 信 息 与 算 机 工 院 算 机 科 与 技 术 人 才 培 养 方 案 ( 代 码 :080901) 一 培 养 目 标 培 养 适 应 国 家 建 设 发 展 需 要, 德 智 体 全 面 发 展, 具 有 良 好 的 科 素 养 和 丰 厚 的 人 文 底 蕴, 掌 握 扎 的 算 机 科 核 心 基 础 理 论 知 识 和 主 流 工 技 术, 了 解 本 的 前 沿 发 展 现 状 和

More information

,,, ( ) ( ), %, %,,,,,,,,,,,,,,,,,,, %,,,,,,,, :,,,,,,,,,,,,,,,,,,,,,,,,,, ( ),,, :., ( ),,,,,, :,, ( ),,

,,, ( ) ( ), %, %,,,,,,,,,,,,,,,,,,, %,,,,,,,, :,,,,,,,,,,,,,,,,,,,,,,,,,, ( ),,, :., ( ),,,,,, :,, ( ),, * ( ) 葛延风 内容提要 : 中国养老保障制度改革的方向是基金预筹积累的个人帐户制度 在向新制度的转轨过程中, 核心的问题是解决老职工的养老金来源 年以来的改 革没有解决这一问题, 以致于陷入困境 作者认为改革的思路是用国有资产存量偿 还对老职工的养老金负债, 在此基础上建立完全的个人帐户制度 医疗和失业保障 改革也应转换思路 医疗保障制度改革应打破城乡分割问题, 建立城乡一体化的保障体系 失业保障不能通过失业保险解决,

More information

new 进行创建对象, 是程序主动去创建依赖对象 ; 而 IoC 是有专门一个容器来创建这些对象, 即由 Ioc 容器来控制对象的创建 ; 谁控制谁? 当然是 IoC 容器控制了对象 ; 控制什么? 那就是主要控制了外部资源获取 ( 不只是对象包括比如文件等 ) 为何是反转, 哪些方面反转了 : 有

new 进行创建对象, 是程序主动去创建依赖对象 ; 而 IoC 是有专门一个容器来创建这些对象, 即由 Ioc 容器来控制对象的创建 ; 谁控制谁? 当然是 IoC 容器控制了对象 ; 控制什么? 那就是主要控制了外部资源获取 ( 不只是对象包括比如文件等 ) 为何是反转, 哪些方面反转了 : 有 本章学习目标 小风 Java 实战系列教程 Spring 框架简介 SpringIOC 的概念和作用 工厂模式设计一个简单的 IOC 容器 SpringIOC 的 XML 方式 HelloWorld SpringIOC 的 XML 方式创建对象配置细节 SpringIOC 的 XML 方式依赖注入 SpringIOC 的注解方式 Spring 整合 Junit 简化测试类编写 1. Spring 框架简介

More information

优迈科技教学大纲2009版本

优迈科技教学大纲2009版本 java 软 件 工 程 师 培 训 教 学 大 纲 1 JAVA 软 件 工 程 师 培 训 教 学 大 纲 深 圳 软 件 园 人 才 实 训 基 地 2009 年 3 月 目 录 java 软 件 工 程 师 培 训 教 学 大 纲 2 教 学 阶 段...3 第 一 章 JAVA 起 步...3 第 二 章 面 向 对 象 的 编 程...4 第 三 章 数 据 结 构 IO 线 程 网 络...5

More information

使用MapReduce读取XML文件

使用MapReduce读取XML文件 使用 MapReduce 读取 XML 文件 XML( 可扩展标记语言, 英语 :extensible Markup Language, 简称 : XML) 是一种标记语言, 也是行业标准数据交换交换格式, 它很适合在系统之间进行数据存储和交换 ( 话说 Hadoop H ive 等的配置文件就是 XML 格式的 ) 本文将介绍如何使用 MapReduce 来读取 XML 文件 但是 Had oop

More information

拦截器(Interceptor)的学习

拦截器(Interceptor)的学习 二 拦截器 (Interceptor) 的学习 拦截器可以监听程序的一个或所有方法 拦截器对方法调用流提供了细粒度控制 可以在无状态会话 bean 有状态会话 bean 和消息驱动 bean 上使用它们 拦截器可以是同一 bean 类中的方法或是一个外部类 下面介绍如何在 Session Bean 类中使用外部拦截器类 @Interceptors 注释指定一个或多个在外部类中定义的拦截器 下面拦截器

More information

2009 年第 6 期 高清总动员 35

2009 年第 6 期 高清总动员 35 要说 08 年最成功的高清机, 非三合一 F1/F2 莫属 它集中了国内不同的高清接收需求, 整合了当时能想到的各种功能, 为欣赏高清奥运, 满足高端发烧人士, 做出了贡献 F1/F2 的成功, 说明不依赖进口, 我们也有能力打造顶级的高清机, 并且更适合国内的使用习惯 不过, 即使 F1/F2 的终极版, 也不兼容 ABS-S 或 ISDB-S, 没有网络功能, 不能 USB 录像等等, 有一定的局限性

More information

等 的氛围 有利于与受评者深入交流 五 进行修正 接下来 就要根据评估的结果进行目标和策略方案的修订 修订 的内容包括 职业的重新选择 职业生涯路线的选择阶段目标的修正 实施措施与行动计划的变更等等 通过反馈评估和修正 应该达到下列目的 对自己的强项充满自信 我知道我的强项是什么 对自己的发展机会有一个清楚的了解 我知道自己什么地方还 有待改进 找出关键的有待改进之处 为这些有待改进之处制定详细的行为改变计划

More information

Struts2自定义类型转换.doc

Struts2自定义类型转换.doc Struts2 自定义类型转换 原理 struts2 的自定义类型转换机制为复杂类型的输入输出处理提供了便捷.struts2 已经为我们提供了几乎所有的 primitive 类型以及常用类型 ( 如 Date) 的类型转换器, 我们也可以为我们自定义类添加自定义类型转化器. struts2 为我们提供了一个类型转化器的入口 : ognl.defaulttypeconverter, 或继承 org.apache.struts2.util.strutstypeconverter,

More information

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit Tomcat Web JUnit Cactus JUnit Java Cactus JUnit 26.1 JUnit Java JUnit JUnit Java JSP Servlet JUnit Java Erich Gamma Kent Beck xunit JUnit boolean JUnit Java JUnit Java JUnit Java 26.1.1 JUnit JUnit How

More information

Microsoft Word - Hibernate与Struts2和Spring组合指导.doc

Microsoft Word - Hibernate与Struts2和Spring组合指导.doc 1.1 组合 Hibernate 与 Spring 1. 在 Eclipse 中, 新建一个 Web project 2. 给该项目增加 Hibernate 开发能力, 增加 Hibernate 相关类库到当前项目的 Build Path, 同时也提供了 hibernate.cfg.xml 这个配置文件 3. 给该项目增加 Spring 开发能力, 增加 spring 相关类库到当前项目的 Build

More information

Spark读取Hbase中的数据

Spark读取Hbase中的数据 Spark 读取 Hbase 中的数据 Spark 和 Flume-ng 整合, 可以参见本博客 : Spark 和 Flume-ng 整合 使用 Spark 读取 HBase 中的数据 如果想及时了解 Spark Hadoop 或者 Hbase 相关的文章, 欢迎关注微信公共帐号 :iteblog_hadoop 大家可能都知道很熟悉 Spark 的两种常见的数据读取方式 ( 存放到 RDD 中 ):(1)

More information

册子0906

册子0906 IBM SelectStack ( PMC v2.0 ) 模块化私有云管理平台 是跨主流虚拟化技术的统一资源云管理平台 01 亮点 : 快速可靠地实现集成化 私有云管理平台 02/03 丰富的功能支持企业数据中心云计算 扩展性强 : 简单易用 : 04/05 功能丰富 : 06/07 为什么选择 IBM SelectStack (PMC v2.0)? 快速实现价值 提高创新能力 降低 IT 成本 降低复杂度和风险

More information

1.JasperReport ireport JasperReport ireport JDK JDK JDK JDK ant ant...6

1.JasperReport ireport JasperReport ireport JDK JDK JDK JDK ant ant...6 www.brainysoft.net 1.JasperReport ireport...4 1.1 JasperReport...4 1.2 ireport...4 2....4 2.1 JDK...4 2.1.1 JDK...4 2.1.2 JDK...5 2.1.3 JDK...5 2.2 ant...6 2.2.1 ant...6 2.2.2 ant...6 2.3 JasperReport...7

More information

序号:001

序号:001 第 一 组 选 题 简 介 序 号 :001 题 目 : 基 于 BPEL 的 网 上 订 餐 系 统 的 设 计 与 实 现 网 上 订 餐 系 统 是 在 互 联 网 上 进 行 菜 单 信 息 发 布 网 上 订 餐 以 及 维 护 客 户 关 系 的 电 子 商 务 系 统, 餐 饮 企 业 可 以 通 过 这 个 电 子 商 务 系 统 发 布 自 己 的 菜 单 信 息 以 供 客 户

More information

Microsoft Word - 九月月刊.docx

Microsoft Word - 九月月刊.docx 梅 Aug 2014 Vol. 1 Issue 7 + 1 常 的 糖尿病篇 Page 1 Ø Ø 我不需要自己, 那是 生的事情? Ø Ø Ø Ø 么 时 药 + more on 2 Lorem 梅 Aug 2014 Vol. 1 Issue 7 Ipsum 于血糖 : 我不需要自己, 那是 生的事情 2 梅 Aug 2014 Vol. 1 Issue 7 Lorem Ipsum 1) 2) 晚

More information

Microsoft PowerPoint - ch6 [相容模式]

Microsoft PowerPoint - ch6 [相容模式] UiBinder wzyang@asia.edu.tw UiBinder Java GWT UiBinder XML UI i18n (widget) 1 2 UiBinder HelloWidget.ui.xml: UI HelloWidgetBinder HelloWidget.java XML UI Owner class ( Composite ) UI XML UiBinder: Owner

More information

Microsoft PowerPoint - plan08.ppt

Microsoft PowerPoint - plan08.ppt 程 序 设 计 语 言 原 理 Principle of Programming Languages 裘 宗 燕 北 京 大 学 数 学 学 院 2012.2~2012.6 8. 面 向 对 象 为 什 么 需 要 面 向 对 象? OO 语 言 的 发 展 面 向 对 象 的 基 本 概 念 封 装 和 继 承 初 始 化 和 终 结 处 理 动 态 方 法 约 束 多 重 继 承 总 结 2012

More information

设计模式 Design Patterns

设计模式 Design Patterns Spring 与 Struts Hibernate 的集成 丁勇 Email:18442056@QQ.com 学习目标 掌握 Spring 与 Struts 的集成 掌握 Spring 与 Hibernate 的集成 学会使用 Spring 实现声明式事务 Spring 与 Hibernate 集成 使用 Spring 简化 Hibernate 编程 使现有使现有 Java Java EE EE 技术更易用

More information

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc References (Section 5.2) Hsuan-Tien Lin Deptartment of CSIE, NTU OOP Class, March 15-16, 2010 H.-T. Lin (NTU CSIE) References OOP 03/15-16/2010 0 / 22 Fun Time (1) What happens in memory? 1 i n t i ; 2

More information

第03章 控制反转(Spring IoC)

第03章  控制反转(Spring IoC) 3 Spring IoC GoF Design Patterns: Elements of Reusable Object-Oriented Software Programming to an Interface not an Implementation Java Java Java GoF Service Locator IoC IoC Spring IoC 3.1 IoC IoC IoC Dependency

More information

Microsoft Word - 在VMWare-5.5+RedHat-9下建立本机QTopia-2.1.1虚拟平台a.doc

Microsoft Word - 在VMWare-5.5+RedHat-9下建立本机QTopia-2.1.1虚拟平台a.doc 在 VMWare-5.5+RedHat-9 下建立 本机 QTopia-2.1.1 虚拟平台 张大海 2008-5-9 一 资源下载 1. 需要以下安装包 : tmake-1.13.tar.gz qtopia-free-source-2.1.1.tar.gz qt-embedded-2.3.10-free.tar.gz qt-x11-2.3.2.tar.gz qt-x11-free-3.3.4.tar.gz

More information

前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii

前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii 前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii C# 7 More Effective C# C# C# C# C# C# Common Language Runtime CLR just-in-time

More information

南威软件股份有限公司

南威软件股份有限公司 发 行 概 况 发 行 股 票 类 型 发 行 股 数 本 次 发 行 股 份 安 排 每 股 面 值 每 股 发 行 价 格 预 计 发 行 日 期 拟 上 市 证 券 交 易 所 发 行 后 总 股 本 人 民 币 普 通 股 A 股 不 超 过 2,500 万 股 本 次 计 划 公 开 发 行 股 票 数 量 不 超 过 2,500 万 股, 占 发 行 后 公 司 总 股 本 的 25%

More information

年第 期

年第 期 年第 期 论虚拟实践的哲学意蕴 孙伟平 信息技术 虚拟技术 实践 实践形态 虚拟实践 所谓虚拟实践 是指人们按照一定的目的 通过数字化中介系统在虚拟时空进行的 主体与虚拟客体双向对象化的感性活动 它是人们有目的 有意识进行的能动的探索和改造 虚拟客体 同时也提升和改造自身的客观活动 是人类在当代技术革命推动下兴起的一种新型的实践活动形态 具有与传统实践迥然不同的特征 虚拟实在性 即时交互性 自由开放性

More information

Hive:用Java代码通过JDBC连接Hiveserver

Hive:用Java代码通过JDBC连接Hiveserver Hive: 用 Java 代码通过 JDBC 连接 Hiveserver 我们可以通过 CLI Client Web UI 等 Hive 提供的用户接口来和 Hive 通信, 但这三种方式最常用的是 CLI;Client 是 Hive 的客户端, 用户连接至 Hive Server 在启动 Client 模式的时候, 需要指出 Hive Server 所在节点, 并且在该节点启动 Hive Server

More information

ChinaBI企业会员服务- BI企业

ChinaBI企业会员服务- BI企业 商业智能 (BI) 开源工具 Pentaho BisDemo 介绍及操作说明 联系人 : 杜号权苏州百咨信息技术有限公司电话 : 0512-62861389 手机 :18616571230 QQ:37971343 E-mail:du.haoquan@bizintelsolutions.com 权限控制管理 : 权限控制管理包括 : 浏览权限和数据权限 ( 权限部分两个角色 :ceo,usa; 两个用户

More information

epub83-1

epub83-1 C++Builder 1 C + + B u i l d e r C + + B u i l d e r C + + B u i l d e r C + + B u i l d e r 1.1 1.1.1 1-1 1. 1-1 1 2. 1-1 2 A c c e s s P a r a d o x Visual FoxPro 3. / C / S 2 C + + B u i l d e r / C

More information

Chapter #

Chapter # 第三章 TCP/IP 协议栈 本章目标 通过本章的学习, 您应该掌握以下内容 : 掌握 TCP/IP 分层模型 掌握 IP 协议原理 理解 OSI 和 TCP/IP 模型的区别和联系 TCP/IP 介绍 主机 主机 Internet TCP/IP 早期的协议族 全球范围 TCP/IP 协议栈 7 6 5 4 3 应用层表示层会话层传输层网络层 应用层 主机到主机层 Internet 层 2 1 数据链路层

More information

领导,我不想写CSS代码.key

领导,我不想写CSS代码.key 领导 我不想写 CSS 张鑫旭 25MIN 2018-03-31 YUEWEN USER EXPERIENCE DESIGN 01 1 YUEWEN USER EXPERIENCE DESIGN 砖家 02 CSS - 艺术家 YUEWEN USER EXPERIENCE DESIGN 03 CSS - 砖家 艺术家 YUEWEN USER EXPERIENCE DESIGN 04 领导, 我不想写

More information

// HDevelopTemplateWPF projects located under %HALCONEXAMPLES%\c# using System; using HalconDotNet; public partial class HDevelopExport public HTuple

// HDevelopTemplateWPF projects located under %HALCONEXAMPLES%\c# using System; using HalconDotNet; public partial class HDevelopExport public HTuple halcon 与 C# 混合编程之 Halcon 代码调用 写在前面 完成 halcon 与 C# 混合编程的环境配置后, 进行界面布局设计构思每一个按钮所需要实现 的功能, 将 Halcon 导出的代码复制至相应的 C# 模块下即可 halcon 源程序 : dev_open_window(0, 0, 512, 512, 'black', WindowHandle) read_image (Image,

More information

Java 1 Java String Date

Java 1 Java String Date JAVA SCJP Java 1 Java String Date 1Java 01 Java Java 1995 Java Java 21 Java Java 5 1-1 Java Java 1990 12 Patrick Naughton C++ C (Application Programming Interface API Library) Patrick Naughton NeXT Stealth

More information

如何掌控你的时间 了解自己的黄金时间 寻找事情的关键步骤 将事情分类处理 化零为整 懂得强化自己 这个假期有点荒废

如何掌控你的时间 了解自己的黄金时间 寻找事情的关键步骤 将事情分类处理 化零为整 懂得强化自己 这个假期有点荒废 YANYUAN VOICE 本期导读 燕园组讯 如何掌控你的时间 了解自己的黄金时间 寻找事情的关键步骤 将事情分类处理 化零为整 懂得强化自己 这个假期有点荒废 永远的分配问题 为什么看重公平? 作为假设的公平 作为期望的公平 不要说应该公平 所谓公平 我眼中的猫 说 纭 卡丢了以后 : 卡奴 的悲哀 众里寻 Ta 你疯了吗? 失败恐惧吞钩现象 信任 濛濛 一眼就看见你, 水瓶 请找出右边两幅图中

More information

云数据库 RDS SDK

云数据库 RDS SDK 云数据库 RDS SDK SDK SDK 下载 SDK 下载 最新版本 java_sdk.zip python_sdk.zip php_sdk.zip c#_sdk.zip 历史版本 2015-11-3 java_sdk.zip python_sdk.zip php_sdk.zip c#_sdk.zip JAVA 教程 JAVA 创建 Access Key 登陆阿里云账号 打开 我的 Access

More information

10-2 SCJP SCJD 10.1 昇陽認證 Java 系統開發工程師 的認證程序 Java IT SCJD

10-2 SCJP SCJD 10.1 昇陽認證 Java 系統開發工程師 的認證程序 Java IT SCJD 10 SCJD 簡介 Java 10-2 SCJP SCJD 10.1 昇陽認證 Java 系統開發工程師 的認證程序 Java IT SCJD 10 SCJD 10-3 Java Java SCJD 7 Swing RMI 10.1.1 The Assignment The Essay 9 10 10-4 SCJP SCJD 90 10.1.2 SCJP Java 90 120 Swing 10

More information

F515_CS_Book.book

F515_CS_Book.book /USB , ( ) / L R 1 > > > 2, / 3 L 1 > > > 2 + - 3, 4 L 1 了解显示屏上显示的图标 Wap 信箱收到一条 Wap push 信息 ( ) GSM 手机已连接到 GSM 网络 指示条越多, 接收质量越好 2 ...........................4.............................. 4 Micro SD (

More information

<4D6963726F736F667420576F7264202D20B9FABCD2BBFAB9D8B0ECB9ABBDA8D6FEBACDB4F3D0CDB9ABB9B2BDA8D6FEC4DCBAC4BCE0B2E2CFB5CDB3C8EDBCFEBFAAB7A2D6B8B5BCCBB5C3F7CAE92E646F63>

<4D6963726F736F667420576F7264202D20B9FABCD2BBFAB9D8B0ECB9ABBDA8D6FEBACDB4F3D0CDB9ABB9B2BDA8D6FEC4DCBAC4BCE0B2E2CFB5CDB3C8EDBCFEBFAAB7A2D6B8B5BCCBB5C3F7CAE92E646F63> 附 件 : 国 家 机 关 办 公 建 筑 和 大 型 公 共 建 筑 能 耗 监 测 系 统 软 件 开 发 指 导 说 明 书 住 房 和 城 乡 建 设 部 二 〇 〇 九 年 二 月 前 言 为 指 导 各 地 国 家 机 关 办 公 建 筑 和 大 型 公 共 建 筑 能 耗 监 测 系 统 建 设, 住 房 和 城 乡 建 设 部 组 织 有 关 专 家, 在 总 结 吸 收 国 内 已

More information

设计模式 Design Patterns

设计模式 Design Patterns 丁勇 Email:18442056@QQ.com 学习目标 掌握 Model I 体系结构 掌握 Model II 体系结构 掌握 MVC 应用程序 Model I 体系结构 6 1 Model I 体系结构结合使用 JSP 页面和 Bean 来开发 Web 应用程序 应用服务器 请求 JSP 页面 响应 Bean 数据库服务器 Model I 体系结构 6 2 Model I 体系结构用于开发简单的应用程序

More information

通过Hive将数据写入到ElasticSearch

通过Hive将数据写入到ElasticSearch 我在 使用 Hive 读取 ElasticSearch 中的数据 文章中介绍了如何使用 Hive 读取 ElasticSearch 中的数据, 本文将接着上文继续介绍如何使用 Hive 将数据写入到 ElasticSearch 中 在使用前同样需要加入 elasticsearch-hadoop-2.3.4.jar 依赖, 具体请参见前文介绍 我们先在 Hive 里面建个名为 iteblog 的表,

More information

國家圖書館典藏電子全文

國家圖書館典藏電子全文 EAI EAI Middleware EAI 3.1 EAI EAI Client/Server Internet,www,Jav a 3.1 EAI Message Brokers -Data Transformation Business Rule XML XML 37 3.1 XML XML XML EAI XML 1. XML XML Java Script VB Script Active

More information

FAQ -PowerDesigner9.5.DOC

FAQ -PowerDesigner9.5.DOC PowerDesigner 9.5 FAQ 1. PowerDesigner PowerDesigner PowerDesigner (CASE Tool,Computer Aided Software Engineering) PowerDesigner 1989 9.5 2. PowerDesigner PowerDesigner Internet ( Java) PowerDesigner 7.0

More information

Guava学习之CharSequenceReader

Guava学习之CharSequenceReader CharSequenceReader 类是以 CharSequence 的形式读取字符 CharSequenceReader 类继承自 Reader 类, 除了 remaining() hasremaining() 以及 checkopen() 函数之后, 其他的函数都是重写 Reader 类中的函数 CharSequenceReader 类声明没有用 public 关键字, 所以我们暂时还不能调用这个类

More information

基于ECO的UML模型驱动的数据库应用开发1.doc

基于ECO的UML模型驱动的数据库应用开发1.doc ECO UML () Object RDBMS Mapping.Net Framework Java C# RAD DataSetOleDbConnection DataGrod RAD Client/Server RAD RAD DataReader["Spell"].ToString() AObj.XXX bug sql UML OR Mapping RAD Lazy load round trip

More information

北京北信源软件股份有限公司招股书(申报稿)

北京北信源软件股份有限公司招股书(申报稿) qimingengz 31 创 业 板 投 资 风 险 提 示 本 次 股 票 发 行 后 拟 在 创 业 板 市 场 上 市, 该 市 场 具 有 较 高 的 投 资 风 险 创 业 板 公 司 具 有 业 绩 不 稳 定 经 营 风 险 高 退 市 风 险 大 等 特 点, 投 资 者 面 临 较 大 的 市 场 风 险 投 资 者 应 充 分 了 解 创 业 板 市 场 的 投 资 风 险 及

More information

PowerPoint 演示文稿

PowerPoint 演示文稿 友乾营 报表的 SQL 植入风险 规避风险 : 让你的报表变的安全起来 SQL 植入的概念 恶意的 SQL 归根结底 : 执行了不该允许执行的 SQL 命令, 达到非法的目的 常见案例 骗过登录验证非法获取账号信息篡改 删除数据 为什么存在 SQL 植入 植入原理 如何攻击 特殊的输入参数 未处理特殊字符 -- # 数据库配置不合理 植入原理 : 案例 1, 特殊输入参数 union or 猜表名

More information

D C 93 2

D C 93 2 D9223468 3C 93 2 Java Java -- Java UML Java API UML MVC Eclipse API JavadocUML Omendo PSPPersonal Software Programming [6] 56 8 2587 56% Java 1 epaper(2005 ) Java C C (function) C (reusability) eat(chess1,

More information

01

01 ZEBRA 技术白皮书 条码编码 101 相关知识介绍 引言 20 70 数据 80 20 90 (JIT) AIAG EIA HIBCC HAZMAT 条码的优势提高数据准确性 99% 85% / / 提升效率 / 2 Zebra Technologies 保持一致性 ID 改进库存和资产管理 成本 / 效益分析 ID ID ID (ERP) RFID Zebra Technologies 3 ID

More information

untitled

untitled ArcGIS Server Web services Web services Application Web services Web Catalog ArcGIS Server Web services 6-2 Web services? Internet (SOAP) :, : Credit card authentication, shopping carts GIS:, locator services,

More information

没 有 多 余 的 Contruol 或 Action 了 原 来 Domain 层 被 服 务 层 Service layer 遮 挡, 在 右 边 图 中, 则 Domain 层 直 接 暴 露 给 前 台 了, 没 有 被 遮 挡, 裸 露 了 这 样 一 步 到 位 实 现 领 域 模 型

没 有 多 余 的 Contruol 或 Action 了 原 来 Domain 层 被 服 务 层 Service layer 遮 挡, 在 右 边 图 中, 则 Domain 层 直 接 暴 露 给 前 台 了, 没 有 被 遮 挡, 裸 露 了 这 样 一 步 到 位 实 现 领 域 模 型 文 章 编 号 :1007-757X(2012)1-0036-04 领 域 驱 动 模 型 的 WEB 软 件 系 统 设 计 研 究 摘 要 : J2EE 3 JDK1.7 Tomcat WEB 关 键 词 : 中 图 分 类 号 :TP311 文 献 标 志 码 :A 0 引 言 Web 软 件 系 统 的 分 层 结 构 典 型 的 J2EE 软 件 系 统 开 发 方 法 分 为 三 层 结

More information

软 件 工 程 专 业 习 指 南 目 录 一 软 件 工 程 专 业 设 置 背 景 与 发 展 前 景... 3 二 软 件 工 程 专 业 实 践 教 条 件... 4 三 软 件 工 程 专 业 课 程 类 型 及 核 方 式... 6 1. 软 件 工 程 专 业 课 程 类 型...7

软 件 工 程 专 业 习 指 南 目 录 一 软 件 工 程 专 业 设 置 背 景 与 发 展 前 景... 3 二 软 件 工 程 专 业 实 践 教 条 件... 4 三 软 件 工 程 专 业 课 程 类 型 及 核 方 式... 6 1. 软 件 工 程 专 业 课 程 类 型...7 计 算 机 系 软 件 工 程 专 业 习 指 南 广 东 科 技 院 计 算 机 系 2015-9-1 软 件 工 程 专 业 习 指 南 目 录 一 软 件 工 程 专 业 设 置 背 景 与 发 展 前 景... 3 二 软 件 工 程 专 业 实 践 教 条 件... 4 三 软 件 工 程 专 业 课 程 类 型 及 核 方 式... 6 1. 软 件 工 程 专 业 课 程 类 型...7

More information

设计模式 Design Patterns

设计模式 Design Patterns 丁勇 Email:18442056@QQ.com 组件技术概述 现在软件开发都已经转向了基于组件的开发, 目前具备代表性的组件技术有微软的 COM COM+, 有 Sun 的 Bean 和 EJB(Enterprise Bean), 另外还有 CORBA(Common Object Request Broker Architecture, 公 共对象请求代理结构 ) Bean Bean 规范将 软件组件

More information

建模与图形思考

建模与图形思考 F06_c 观摩 :ContentProvider 基於軟硬整合觀點 架构與 DB 引擎移植方法 ( c) By 高煥堂 4 通用性基类 ContentProvider 基於軟硬整合觀點 的使用范例 刚才的范例里, 我们直接使用 DataPersist 类的接口来与 SQLite 沟通 本节将替 DataPersist 配上 ContentProvider 基类, 让 Client 能透过 ContentProvider

More information

教学〔2016〕120号

教学〔2016〕120号 河 南 省 教 育 厅 教 学 2016 120 号 河 南 省 教 育 厅 关 于 对 口 招 收 中 等 职 业 学 校 毕 业 生 进 入 普 通 高 等 学 校 学 习 的 通 知 各 省 辖 市 省 直 管 县 ( 市 ) 教 育 局, 省 各 级 招 生 机 构, 各 普 通 高 等 学 校 省 属 中 等 职 业 学 校 : 为 贯 彻 党 的 十 八 大 和 十 八 届 三 中 四

More information