运用Command设计模式释放Server资源

       Server可能与多个系统建立连接,当Shutdown的时候需要释放资源。比如数据库连接,Socket连接等等。当然也可能需要释放本地资源。本文主要展示如何运用Command设计模式来实现服务器资源的释放。得到的效果是不同的资源释放过程具有独立性,新增释放过程不会影响到原来的架构设计。


       首先定义一个释放资源的统一接口Releaser,为Command模式中的Command。所有释放资源的具体类都实现该接口。代码如下:


/**
 * 释放资源的接口
 */
public interface Releaser {
	void release();
}

     接下来设计一个命令管理器,统一管理释放资源的命令。该类不是传统的Command模式的一部分。项目中用Spring框架,命令通过Spring IOC注入进来。解耦了命令与管理器。管理器代码如下:

/**
 * Server正常关闭时释放资源的类
 */
public class ReleaserContainer {
	private static Logger log = LoggerFactory
			.getLogger(ReleaserContainer.class);

	private List<Releaser> releaserList;

	public ReleaserContainer() {
	}

	private void addReleaseHook(final Releaser releaser) {
		Thread thread = new Thread() {
			@Override
			public void run() {
				releaser.release();
			}
		};

		Runtime.getRuntime().addShutdownHook(thread);
	}

	public List<Releaser> getReleaserList() {
		return releaserList;
	}

	public void setReleaserList(List<Releaser> releaserList) {
		this.releaserList = releaserList;

		if (this.releaserList != null && this.releaserList.size() > 0) {
			log.info("Starting add releasers' hook...");

			for (Releaser releaser : this.releaserList) {
				addReleaseHook(releaser);
			}

			log.info("Add releasers' hook completed!");
		}
	}
}

值得注意的是当释放资源命令注入管理器之后会马上挂到Java正常退出的钩子上。Runtime.getRuntime().addShutdownHook(thread)。

对应的Spring配置如下:

<bean id="releaserContainer" class="com.mt.kms.release.ReleaserContainer">
		<property name="releaserList">
			<list>
				<ref bean="socketConnectionReleaser" />
				<ref bean="databaseConnectionReleaser" />
			</list>
		</property>
</bean>


   最后就是具体的去实现资源的释放命令,下面是JDBC Pool和Socket pool的释放。

/**
 * 释放Database JDBC connection pool的类
 */
public class DatabaseConnectionReleaser implements Releaser,
		ApplicationContextAware {
	private static Logger log = LoggerFactory
			.getLogger(DatabaseConnectionReleaser.class);

	private ApplicationContext appContext;

	@Override
	public void release() {
		if (appContext != null) {
			// 从Spring容器中找到JDBC connection pool并释放资源
			BasicDataSource dataSource = (BasicDataSource) appContext
					.getBean("dataSource");
			if (dataSource != null) {
				try {
					log.info("Starting release jdbc connection poll...");
					dataSource.close();
					log.info("Jdbc connection poll releasing completed!");
				} catch (SQLException e) {
					e.printStackTrace();
					log.error("Jdbc connection poll releasing failed!", e);
				}
			}
		}
	}

	@Override
	public void setApplicationContext(ApplicationContext appContext)
			throws BeansException {
		this.appContext = appContext;
	}
}


/**
 * 释放Socket 连接
 */
public class SocketConnectionReleaser implements Releaser {
	private static Logger log = LoggerFactory
			.getLogger(SocketConnectionReleaser.class);
	
	private DataSourceDAO dataSourceDAO;

	@Override
	public void release() {
		log.info("Starting release socket connections...");
		dataSourceDAO.releaseAllConnections();
		log.info("Socket connections releasing completed!");
	}

	public DataSourceDAO getDataSourceDAO() {
		return dataSourceDAO;
	}

	public void setDataSourceDAO(
			DataSourceDAO dataSourceDAO) {
		this.dataSourceDAO = dataSourceDAO;
	}
}

Spring配置如下

<!-- Release resources after server shutdown -->
<bean id="socketConnectionReleaser" class="com.mt.kms.release.SocketConnectionReleaser" />
<bean id="databaseConnectionReleaser" class="com.mt.kms.release.DatabaseConnectionReleaser" />

总结:通过以上的设计,需要释放新的资源时,只需要实现Releaser接口并且注入到ReleaserContainer中即可,完全不需要更改原来的代码。如果没有使用Spring,可以通过XML注册释放命令的方式来实现它们之间的解耦。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值