原型模式

这篇文章的第一个设计模式是原型。可以通过官方文档查找有关Spring作用域中的bean作用域的文章中介绍了类似的概念(prototype)。原型设计模式与有用相同名称的(prototype)作用域有点相似。此设计模式允许通过复制已存在的对象来创建一个对象的实例。副本应该是真正的副本。这意味着新对象的所有属性应与复制对象的属性相同。如果不清楚,比一个简单的JUnit案例更好的说明:

public class PrototypeTest {

@Test

public void test() {

Robot firstRobot = new Robot("Droid#1");

Robot secondRobot = (Robot) firstRobot.clone();

assertTrue("Cloned robot's instance can't be the same as the"

+" source robot instance",

firstRobot != secondRobot);

assertTrue("Cloned robot's name should be '"+firstRobot.getName()+"'"

+" but was '"+secondRobot.getName()+"'",

secondRobot.getName().equals(firstRobot.getName()));

}

}

class Robot implements Cloneable {

private String name;

public Robot(String name) {

this.name = name;

}

public String getName() {

return this.name;

}

protected Object clone() throws CloneNotSupportedException {

return super.clone();

}

}

Spring中,在org.springframework.beans.factory.support.AbstractBeanFactory中使用一种特定的原型设计模式,它将初始化bean原型作用域。新对象基于配置文件中的bean定义。我们可以看到,在给定的例子中:

<bean id="shoppingCart" class="com.waitingforcode.data.ShoppingCart" scope="prototype">

<property name="id" value="9"></property>

</bean>

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations={"applicationContext-test.xml"})

public class SpringPrototypeTest {

@Autowired

private BeanFactory beanFactory;

@Test

public void test() {

ShoppingCart cart1 = (ShoppingCart) beanFactory.getBean("shoppingCart");

assertTrue("Id of cart1 should be 9 but was "+cart1.getId(),

cart1.getId() == 9);

cart1.setId(100);

ShoppingCart cart2 = (ShoppingCart) beanFactory.getBean("shoppingCart");

assertTrue("Id of cart2 should be 9 but was "+cart2.getId(),

cart2.getId() == 9);

assertTrue("Id of second cart ("+cart2.getId()+") shouldn't be the same as the first one: "+cart1.getId(),

cart1.getId() != cart2.getId());

cart2.setId(cart1.getId());

assertTrue("Now (after cart2.setId(cart1.getId())), the id of second cart ("+cart2.getId()+") should be the same as the first one: "

+cart1.getId(), cart1.getId() == cart2.getId());

assertTrue("Both instance shouldn't be the same", cart1 != cart2);

}

}

从前面的例子可以看出,ShoppingCart实例是直接从bean定义创建的。最初,cart1cart2对象的id值为9.它在测试结束时被修改,以证明两个引用都属于两个不同的对象。

对象池

Spring中使用的另一个模型是对象池设计模式。其主要目的在于在一个池中保存特定数量的对象,并根据需要重新使用。通过它,我们可以改善我们想要使用巨型对象的响应时间。巨型意味着这些对象的构造需要很多时间(例如:持有数据库连接的对象),最好重用已经存在的和未获取的对象,而不是创建新对象。

Spring还使用线程池来管理其调度部分。一些示例位于org.springframework.scheduling.concurrent中。我们检索数据库(Spring JDBC)项目中的对象池的想法。数据库连接池不是由Spring直接实现的,而是适用于Spring工作方式的项目,如C3P0Jakarta Commons DBCP连接池。

观察者

这里呈现的最后一个设计模式是观察者。当一个或几个课程正在等待具体事件时可以使用它。观察者模式由一个科目和观察员名单组成。一个很好的例子就是GUI界面,其中点击按钮(按钮是主题)会引起听众(观察者)启动的一些操作(再说的直白点就是电影院一场电影这个subject,需要观众(也就是观察者咯),电影产生的一些画面产生的事件,比如恐怖 电影给男人女人带来的不同的感官的感受,传播到观察者也就是观众的眼里所带来的不一样的反应,这个中间一般会添加一个事件传播者,在后面解释Spring的例子的时候会说到),例如:打开一个新页面这个动作。可以参考下面的例子:

public class ObserverTest {

@Test

public void test() {

Observer pageOpener = new PageOpener();

Observer register = new Register();

Button btn = new Button();

btn.addListener(pageOpener);

btn.addListener(register);

btn.clickOn();

assertTrue("Button should be clicked but it wasn't",

btn.wasClicked());

assertTrue("Page opener should be informed about click but it wasn't",

pageOpener.wasInformed());

assertTrue("Register should be informed about click but it wasn't",

register.wasInformed());

}

}

class Button {

private boolean clicked;

private List<observer> listeners;

public List<observer> getListeners() {

if (this.listeners == null) {

this.listeners = new ArrayList<observer>();

}

return this.listeners;

}

public void addListener(Observer observer) {

getListeners().add(observer);

}

public boolean wasClicked() {

return this.clicked;

}

public void clickOn() {

this.clicked = true;

informAll();

}

private void informAll() {

for (Observer observer : getListeners()) {

observer.informAboutEvent();

}

}

}

abstract class Observer {

protected boolean informed;

public void informAboutEvent() {

this.informed = true;

}

public boolean wasInformed() {

return this.informed;

}

}

class PageOpener extends Observer {

@Override

public void informAboutEvent() {

System.out.println("Preparing download of new page");

super.informAboutEvent();

}

}

class Register extends Observer {

@Override

public void informAboutEvent() {

System.out.println("Adding the action to register");

super.informAboutEvent();

}

}

可以看到,关于我们的Button实例点击的事件被发送到所有的观察者对象。从这些对象开始下载页面内容,第二个将在事件的信息保存在注册表中。在Spring中,观察者设计模式用于将与应用程序上下文相关的事件传输到org.springframework.context.ApplicationListener的实现。要了解它们的实现方法,我们来看一下AbstractApplicationContext类(老版本的代码,新版本的请自行对照):

public abstract class AbstractApplicationContext extends DefaultResourceLoader

implements ConfigurableApplicationContext, DisposableBean {

/** Statically specified listeners */

private Set<applicationlistener<?>> applicationListeners = new LinkedHashSet<applicationlistener<?>>();

// some other fields and methods

@Override

public void addApplicationListener(ApplicationListener<?> listener) {

if (this.applicationEventMulticaster != null) {

this.applicationEventMulticaster.addApplicationListener(listener);

}

else {//新版本这里直接咔嚓掉,上面的applicationEventMulticaster一旦为空,就会报错的

this.applicationListeners.add(listener);

}

}

/**

* Return the list of statically specified ApplicationListeners.

*/

public Collection<applicationlistener<?>> getApplicationListeners() {

return this.applicationListeners;

}

/**

* Add beans that implement ApplicationListener as listeners.

* Doesn't affect other listeners, which can be added without being beans.

*/

protected void registerListeners() {

// Register statically specified listeners first.

for (ApplicationListener<?> listener : getApplicationListeners()) {

getApplicationEventMulticaster().addApplicationListener(listener);

}

// Do not initialize FactoryBeans here: We need to leave all regular beans

// uninitialized to let post-processors apply to them!

String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);

for (String lisName : listenerBeanNames) {

getApplicationEventMulticaster().addApplicationListenerBean(lisName);

}

}

}

在提供的代码中,监听器在内部添加到应用程序上下文类中,并且在registerListeners()方法之后,它们被注册到由接口org.springframework.context.event.ApplicationEventMulticaster表示的适当的事件多路广播器(因为有很多listeners)。EventMulticaster负责管理不同的listener和向他们发布事件。

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

private Executor taskExecutor;

private ErrorHandler errorHandler;

public SimpleApplicationEventMulticaster() {

}

public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {

this.setBeanFactory(beanFactory);

}

public void setTaskExecutor(Executor taskExecutor) {

this.taskExecutor = taskExecutor;

}

protected Executor getTaskExecutor() {

return this.taskExecutor;

}

public void setErrorHandler(ErrorHandler errorHandler) {

this.errorHandler = errorHandler;

}

protected ErrorHandler getErrorHandler() {

return this.errorHandler;

}

public void multicastEvent(ApplicationEvent event) {

this.multicastEvent(event, this.resolveDefaultEventType(event));

}

//发布事件:通过池执行任务的方式来做并发处理,这样就把之前的对象池模式给利用上了

public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {

ResolvableType type = eventType != null?eventType:this.resolveDefaultEventType(event);

Iterator var4 = this.getApplicationListeners(event, type).iterator();

while(var4.hasNext()) {

final ApplicationListener<?> listener = (ApplicationListener)var4.next();

Executor executor = this.getTaskExecutor();

if(executor != null) {

executor.execute(new Runnable() {

public void run() {

SimpleApplicationEventMulticaster.this.invokeListener(listener, event);

}

});

} else {

this.invokeListener(listener, event);

}

}

}

...

}

这次我们讲3种设计模式:用于在同一个调用作用域内创建bean的原型,避免重新创建巨型对象的对象池,以及将应用程序的上下文事件分派给适当的监听器的观察者。

Spring框架中的设计模式(三)相关推荐

  1. Spring框架中的设计模式(一)

    设计模式有助于遵循良好的编程实践.作为最流行的Web框架之一的Spring框架也使用其中的一些. 本文将介绍Spring Framework中使用的设计模式.这是5篇专题文章的第一部分.这次我们将发现 ...

  2. Spring框架中的设计模式(四)

    适配器 当我们需要在给定场景下(也就是给定接口)想要不改变自身行为而又想做到一些事情的情况下(就是我给电也就是接口了,你来做事也就是各种电器),使用适配器设计模式(这里再说一点,就相当于我们再一个规章 ...

  3. Spring框架中的设计模式(二)

    在上一篇中我们在Spring中所谈到的设计模式涉及到了创建模式三剑客和1个行为模式(解释器模式).这次我们会将眼光更多地关注在具有结构性和行为性的设计模式上. 在这篇文章中,我们将看到每个类型的两种模 ...

  4. Spring框架中的设计模式(五)

    命令模式 这篇文章描述的第一个行为设计模式是命令.它允许将请求封装在一个对象内并附加一个回调动作(每次遇到所所谓的回调大家就只需要理解为一个函数方法就好,省的去浪费那么多脑子).请求被封装在命令对象之 ...

  5. Spring框架中常用的设计模式详解

    一.浅谈控制反转(IOC)与依赖注入(DI) IOC(Inversion of Control)是Spring中一个非常重要的概念,它不是什么技术,而是一种解耦的设计思想.它主要的额目的是借助于第三方 ...

  6. 浅谈Spring框架应用的设计模式(一)——工厂模式

    文章目录 前言 一.工厂模式介绍 1.简单工厂模式 (1)静态工厂模式 (2)利用反射机制实现的简单工厂 2.工厂方法模式 3.抽象工厂模式 二.Spring框架中工厂模式的重要应用 1.BeanFa ...

  7. Spring框架中的控制反转和依赖注入

    控制反转: 控制反转是用来降低代码之间的耦合度的,基本思想就是借助"第三方"实现具有依赖对象的解耦. 为什么需要控制反转,因为项目中对象或多或少存在耦合.控制反转的关键在于Ioc容 ...

  8. Spring框架中的Bean

    1.什么是Bean? 在Spring框架中,Bean是指一个由Spring容器管理的对象.这个对象可以是任何一个Java类的实例,例如数据库连接.业务逻辑类.控制器等等.Bean实例的创建和管理是由S ...

  9. 在Spring 框架中如何更有效的使用JDBC?

    使用Spring JDBC 框架,资源管理以及错误处理的代价都会减轻.开发人员只需通过statements 和queries 语句从数据库中存取数据.Spring 框架中通过使用模板类能更有效的使用J ...

最新文章

  1. 报错解决:Liquid Warning: Liquid syntax error (line 2): Expected dotdot but found id in {{(site.github.p
  2. c++中调用python脚本提示 error LNK2001: 无法解析的外部符号 __imp_Py_Initialize等错误的解决方法
  3. 如何从SAP中连接其他数据库
  4. 模板:后缀自动机(SAM)
  5. 前端学习(670):分支流程控制if
  6. 【Python 必会技巧】使用 Python 追加写入 json 文件或更改 json 文件中的值
  7. [转载] Python高级变量(列表、元组、字典、字符串、公共方法)
  8. 重磅出击,体验Win2008 Hyper-V(下)
  9. jqueryui时间插件_jQueryUI AutoComplete插件
  10. 那些月入5000的人,凭什么比你更早买房买车?
  11. 遥感影像单波段辐射定标处理
  12. android go官方下载,dji go 4 app官网下载-DJI GO 4 安卓版v4.3.40-pc6智能硬件网
  13. ArcGIS矢量数据重分类
  14. 游戏3d模型如何放到计算机中,三维建模技术在三维游戏中的应用
  15. 用Python写一个任务管理器进行工作协调
  16. 7号团队-团队任务5:项目总结会
  17. Fetcher failure for URL: ‘gitsm://github.com/Xilinx/qemu.git;protocol=https petalinux build 问题
  18. pythonbmi代码_用python写一个BMI体制指数测试
  19. aftershokz蓝牙搜不到_硬核!小程序时怎么控制蓝牙设备的?
  20. 北大SQL数据库视频教程

热门文章

  1. Ubuntu 16.04下Markdown编辑器Haroopad
  2. bs4抓起大众点评的用户评论
  3. CentOS 5.5高负载下,网卡会自动断开
  4. 使用各种方法加速大型矩阵运算的效率对比
  5. js 获取表格数据(表单变量值)
  6. XML数据的分页显示
  7. 解复用FLV文件(基于FFMPEG解析FLV(h264+aac))
  8. Ubuntu16.04安装Mininet
  9. Pygame:编写一个小游戏
  10. intel 965集成显卡开启ubuntu9.10的3d效果