上一篇讲的是容器工厂的原型。

我们可以不必通过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

容器工厂(原型&单例)的更多相关文章

  1. OpenJDK源码研究笔记(十三):Javac编译过程中的上下文容器(Context)、单例(Singleton)和延迟创建(LazyCreation)3种模式

    在阅读Javac源码的过程中,发现一个上下文对象Context. 这个对象用来确保一次编译过程中的用到的类都只有一个实例,即实现我们经常提到的"单例模式". 今天,特意对这个上下文 ...

  2. Spring容器-ApplicationContext的单例设计

    Spring容器-ApplicationContext的单例设计   每次通过new创建一个ApplicationContext容器,都会执行refresh方法,看源代码了解到这个refresh方法会 ...

  3. 初探Java设计模式1:创建型模式(工厂,单例等)

    Java 设计模式 一直想写一篇介绍设计模式的文章,让读者可以很快看完,而且一看就懂,看懂就会用,同时不会将各个模式搞混.自认为本文还是写得不错的,花了不少心思来写这文章和做图,力求让读者真的能看着简 ...

  4. C#中的简单工厂和单例

    下面首先来说说简单工厂 举个例子: 首先是父类 public abstract class Pizza { public abstract string Info(); } } 子类 public c ...

  5. 我心中的核心组件(可插拔的AOP)~第十五回 我的日志组件Logger.Core(策略,模版方法,工厂,单例等模式的使用)

    回到目录 之前的讲过两篇关于日志组件的文章,分别是<第一回  日志记录组件之自主的Vlog>和<第三回  日志记录组件之log4net>,而今天主要说一下我自己开发的另一种日志 ...

  6. Java-马士兵设计模式学习笔记-工厂模式-单例及多例

    一.单例的作用是用于控制类的生成方式,而不让外部类任意new对象 1.Car.java import java.util.ArrayList; import java.util.List; publi ...

  7. spring容器bean的作用域 & spring容器是否是单例的一些问题

    Spring容器中Bean的作用域 当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域.Spring支持如下5种作用域: singleto ...

  8. 【spring容器bean的作用域+spring容器是否是单例的一些问题】

    Spring容器中Bean的作用域 当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域.Spring支持如下5种作用域: singleto ...

  9. php设计模式 工厂、单例、注册树模式

    Source Code Pro字体  easyphp 命名空间:隔离类和函数,php5.3以后 //test5.php<?php namespace Test5;//命名空间必须是程序脚本的第一 ...

随机推荐

  1. Centos7 安装 Ipython的方法

    环境:Centos7 最小化安装yum源设置:阿里的base源和epel源python版本:2.7.5 yum install -y python2-pip.noarchyum install -y ...

  2. ELK之安装了search guard认证后安装elasticsearch-head

    安装searc guard参考https://www.cnblogs.com/minseo/p/10576126.html 安装elasticsearch-head参考 https://www.cnb ...

  3. ES6 函数

    函数参数的扩展 默认参数 基本用法 function fn(name,age=17){ console.log(name+","+age); } fn("Amy" ...

  4. vue中使用mui滑动条无法正常滑动

    需要引入 `mui.min.js`  引入之后浏览器会报错,mui.min.js中的'caller', 'callee', and 'arguments'是不严格模式的js,而webpack中是严格模 ...

  5. 3、jeecg 笔记之 模糊查询

    1.前言 jeecg 考虑到默认模糊查询的话,会增加系统压力,导致查询慢,本来系统就挺那啥的... 2.方式一之实体赋值 实体重新赋值查询,用 * %% * 实现,我们知道 sql 中通常使用 % 去 ...

  6. 关于maven-resources-plugin配置的隐藏的坑

    昨天发现一个问题, 一个第三方证书的文件存放于resources文件夹下,在本地环境使用该证书进行加密调用第三方接口,没有任何问题,但是发布到测试环境和生产环境(linux)报错,提示证书工厂无法初始 ...

  7. python框架之Django(13)-admin组件

    使用 Django 提供了基于 web 的管理工具. Django 自动管理工具是 django.contrib 的一部分.你可以在项目的 settings.py 中的 INSTALLED_APPS ...

  8. form提交循环

    使用ajax提交数据时,如果数据非常多,提交会比较麻烦,这时可以给form表一个id=“form”,用serializeArray()方法进行提交. erializeArray()方法通过序列化表单值 ...

  9. css设置input获得焦点的样式

    input:focus{ 样式; } 这样就ok

  10. python模拟面试技术题答案

      目录 Python4期模拟面试技术面试题答案............................................................................ ...