容器工厂(原型&单例)
上一篇讲的是容器工厂的原型。
我们可以不必通过new关键之创建实例,可以直接取容器里面的实例。
我们可以发现,在对比他们的地址值的时候,他们是相同的为true。
如果我们需要的是不一样的呢。也就是有一些特殊的操作需要到的是单例地址。
下面让我们看看如何创建一个可以随意切换原型&单例的容器工厂吧。
我们在上一篇原型的容器工厂上稍微做一下改造就OK了!
添加一个描述bean的类,封装了配置文件bean的类
public class Definition {
//bean的唯一标识
private String id;
//bean的完整类名
private String className;
//bean的创建方式
private String scope = "singleton"; public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getClassName() {
return className;
} public void setClassName(String className) {
this.className = className;
} public String getScope() {
return scope;
} public void setScope(String scope) {
this.scope = scope;
}
}
第二,我们需要在容器工厂的类里面做出稍稍的改动。
如下:
public class ContainerFactoryTwo {
//单例的容器(Singleton)
private static Map<String,Object> singleton = new HashMap<String,Object>(); //原型的容器(prototype)
private static Map<String,Definition> prototype = new HashMap<String,Definition>(); //初始化
public ContainerFactoryTwo(String resourcePath){
initPrototype(resourcePath);
initSingleton();
} public void initPrototype(String resourcePath){
//创建SAX解析器
SAXReader reader = new SAXReader(); try {
Document document = reader.read(Thread.currentThread().getContextClassLoader().getResourceAsStream(resourcePath));
Element root = document.getRootElement();
List<Element> list = root.elements();
for (Element e:list){
String id = e.attributeValue("id");
String className = e.attributeValue("class");
String scope = e.attributeValue("scope");
//构建bean的定义
Definition def = new Definition();
def.setId(id);
def.setClassName(className);
if(scope!=null){
def.setScope(scope);
}
prototype.put(id,def);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
} /**
* 初始化单利容器
*/ private void initSingleton(){
//遍历prototype里面的值做出判断
for (String key : prototype.keySet()) {
Definition def = prototype.get(key);
//如果是判断是否是singleton
if("singleton".equals(def.getScope())){
try {
//将实例化对象保存到singleton的map里
singleton.put(key, Class.forName(def.getClassName()).newInstance());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
public Object getBean(String name){
return getContainerBean(name);
} public <T> T getBean(String name, Class<T> clazz){
return (T)getContainerBean(name);
} private Object getContainerBean(String name){
//获取作用域属性
String scope = prototype.get(name).getScope();
try {
//三目运算,singleton在scope里面?是的话就之前前者(K对应的已经是一个Object对象)否则执行后者,通过类加载返回一个对象
return ("singleton".equals(scope))?singleton.get(name):
Class.forName(prototype.get(name).getClassName()).newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
} }
测试:
public class Main {
public static void main(String[] args) {
//创建工厂
ContainerFactoryTwo factory = new ContainerFactoryTwo("beans.xml"); Phone phone1 = factory.getBean("OppoPhone", Phone.class);//singleton
Phone phone2 = factory.getBean("OppoPhone", Phone.class);//singleton Pad pad1 = (Pad) factory.getBean("OppoPad", Pad.class);//prototype
Pad pad2 = (Pad) factory.getBean("OppoPad", Pad.class);//prototype
System.out.println(phone1==phone2);
System.out.println(pad1==pad2);
//phone1.call();
}
}
结果为:
true
false
注意:在XML文件里面的scope
决定单例或者是原型容器在于Map
容器工厂(原型&单例)的更多相关文章
- OpenJDK源码研究笔记(十三):Javac编译过程中的上下文容器(Context)、单例(Singleton)和延迟创建(LazyCreation)3种模式
在阅读Javac源码的过程中,发现一个上下文对象Context. 这个对象用来确保一次编译过程中的用到的类都只有一个实例,即实现我们经常提到的"单例模式". 今天,特意对这个上下文 ...
- Spring容器-ApplicationContext的单例设计
Spring容器-ApplicationContext的单例设计 每次通过new创建一个ApplicationContext容器,都会执行refresh方法,看源代码了解到这个refresh方法会 ...
- 初探Java设计模式1:创建型模式(工厂,单例等)
Java 设计模式 一直想写一篇介绍设计模式的文章,让读者可以很快看完,而且一看就懂,看懂就会用,同时不会将各个模式搞混.自认为本文还是写得不错的,花了不少心思来写这文章和做图,力求让读者真的能看着简 ...
- C#中的简单工厂和单例
下面首先来说说简单工厂 举个例子: 首先是父类 public abstract class Pizza { public abstract string Info(); } } 子类 public c ...
- 我心中的核心组件(可插拔的AOP)~第十五回 我的日志组件Logger.Core(策略,模版方法,工厂,单例等模式的使用)
回到目录 之前的讲过两篇关于日志组件的文章,分别是<第一回 日志记录组件之自主的Vlog>和<第三回 日志记录组件之log4net>,而今天主要说一下我自己开发的另一种日志 ...
- Java-马士兵设计模式学习笔记-工厂模式-单例及多例
一.单例的作用是用于控制类的生成方式,而不让外部类任意new对象 1.Car.java import java.util.ArrayList; import java.util.List; publi ...
- spring容器bean的作用域 & spring容器是否是单例的一些问题
Spring容器中Bean的作用域 当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域.Spring支持如下5种作用域: singleto ...
- 【spring容器bean的作用域+spring容器是否是单例的一些问题】
Spring容器中Bean的作用域 当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域.Spring支持如下5种作用域: singleto ...
- php设计模式 工厂、单例、注册树模式
Source Code Pro字体 easyphp 命名空间:隔离类和函数,php5.3以后 //test5.php<?php namespace Test5;//命名空间必须是程序脚本的第一 ...
随机推荐
- HttpRequest获得服务端和客户端的详细信息
参考文档:http://blog.csdn.net/u012104100/article/details/43051301 http://blog.csdn.net/u011162260/articl ...
- ThinkPHP缓存技术(S(),F(),查询缓存,静态缓存)
直接查看原网址 https://blog.csdn.net/u010081689/article/details/47976271
- mui 事件管理及自定义事件详解
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
- css的小知识3
1.补充 margin的margin:0 auto:会解决元素的居中,前提是给这个元素设置width 2.css的层叠问题 css有两个性质 1.继承性 2.层叠性 选择器的一种选择能力,谁的权重大 ...
- BASE64和图片之间的互相转换
package com.test.demo; import java.io.FileInputStream; import java.io.FileOutputStream; import java. ...
- rocketMQ安装部署详细解析
近来研究了Apache开源项目rocketMQ(原为阿里项目),并在两台linux服务器上完成了部署,现在整理下,供大家参考学习. 一.简介rocketMQRocektMQ是阿里巴巴在2012年开源的 ...
- luogu2839 [国家集训队]middle
题目链接:洛谷 题目大意:给定一个长度为$n$的序列,每次询问左端点在$[a,b]$,右端点在$[c,d]$的所有子区间的中位数的最大值.(强制在线) 这里的中位数定义为,对于一个长度为$n$的序列排 ...
- MongoDB 备份(mongodump)与恢复(mongorestore)
MongoDB 备份(mongodump)与恢复(mongorestore) 备份:使用mongodump命令导出所有数据库到指定目录 参数说明: --host:MongoDB所在服务器IP. -- ...
- 家庭记账本之微信小程序(二)
在网上查阅了资料后,了解到了在完成微信小程序之前要完成注册阶段的工作,此次在这介绍注册阶段的流程. 1.首先你要确定小程序的定位.目的以及文案资料等(准备工作). 2.打开微信公众平台官网,点击右上角 ...
- 15.IEnumerable和IEnumerator
先说IEnumerable,我们每天用的foreach你真的懂它吗? 阅读目录 自己实现迭代器 yield的使用 怎样高性能的随机取IEnumerable中的值 我们先思考几个问题: 为什么在fore ...