zoukankan      html  css  js  c++  java
  • 【Spring实战】—— 3 使用facotry-method创建单例Bean总结

    如果有这样的需求

      1 不想再bean.xml加载的时候实例化bean,而是想把加载bean.xml与实例化对象分离。

      2 实现单例的bean

    以上的情况,都可以通过工厂方法factory-method来创建bean

    这样再加载bean.xml时,不会直接实例化bean,而是当调用factory-method所指的方法时,才开始真正的实例化。

      首先看一下传统的单例模式的实现方式:

      1 最原始的实现单例模式的方法(存在线程不安全):

    public class SingletonOne {
        private static SingletonOne instance = null;
        private SingletonOne() {}
        public static SingletonOne getInstance() {
            if (instance == null) {
                instance = new SingletonOne(); 
            }
            return instance;
        }
    }    

      但是这种方法有一个弊端,就是存在线程的不安全!

      比如当两个线程同时进入if(instance == null)时,一个线程判断了当前为空,然后切换到另一个线程,这个线程也判断为空。然后切换回第一个线程,进行实例化,再切换到第二个线程,进行实例化。这样就存在了两个实例。

      2 通过关键字Synchronized强制线程同步 

    package com.something.singleton;
    public class SingletonTwo {
        private static SingletonTwo instance = null;
        private SingletonTwo() {}
        public static synchronized SingletonTwo getInstance() {
            if (instance == null) {
                instance = new SingletonTwo();
            }
            return instance;
        }
    }

      这样当线程进行到getInstance会同步的进行,不会有线程安全问题,但是不仅仅是实例化,每次调用也需要同步,这样就会造成很多资源的浪费。

      3 通过静态内部类进行单例

    public class SingletonThree {
        private static class SingletonHolder{
            static SingletonThree instance = new SingletonThree();
        }
        
      private SingletonThree() {} public static SingletonThree getInstance() { return SingletonHolder.instance; } }

      这种方法时最推荐的一种方法,由于Java的调用机制,SingletonHolder只有在调用getInstance的时候才会加载,而内部的静态类只会被加载一次,因此又是线程安全的。

      总结起来

      第一种方法,是存在线程安全问题的。

      第二种方法,则消耗了一定的资源。

      第三种方法,比较推荐。

    通过spring的factory-method来创建单例的bean

      首先通过静态内部类创建一个单例对象

    package com.spring.test.factorymethod;
    
    public class Stage {
        public void perform(){
            System.out.println("演出开始...");
        }
        private Stage(){
            
        }
        private static class StageSingletonHolder{
            static Stage instance = new Stage();
        }
        public static Stage getInstance(){
            return StageSingletonHolder.instance;
        }
    }

      在spring配置文件中指定加载的方法getInstance

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.springframework.org/schema/beans"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
         <bean id="theStage" class="com.spring.test.factorymethod.Stage"
             factory-method="getInstance"></bean>
    </beans>

      通过应用上下文调用bean获取实例

    package com.spring.test.factorymethod;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class test {
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
            Stage stage = ((Stage)ctx.getBean("theStage"));//.getInstance();
            stage.perform();
        }
    }

      执行结果

    一月 24, 2015 6:38:18 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@512dbd1a: startup date [Sat Jan 24 18:38:18 CST 2015]; root of context hierarchy
    一月 24, 2015 6:38:19 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    信息: Loading XML bean definitions from class path resource [bean.xml]
    一月 24, 2015 6:38:19 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
    信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2d1879ea: defining beans [duke,sonnet29,poeticDuke,theStage]; root of factory hierarchy
    演出开始...
  • 相关阅读:
    -bash: fork: Cannot allocate memory 问题的处理
    Docker top 命令
    docker常见问题修复方法
    The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
    What's the difference between encoding and charset?
    hexcode of é î Latin-1 Supplement
    炉石Advanced rulebook
    炉石bug反馈
    Sidecar pattern
    SQL JOIN
  • 原文地址:https://www.cnblogs.com/xing901022/p/4246308.html
Copyright © 2011-2022 走看看