001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.util.function; 018 019import java.util.function.Supplier; 020 021import org.springframework.lang.Nullable; 022import org.springframework.util.Assert; 023 024/** 025 * A {@link java.util.function.Supplier} decorator that caches a singleton result and 026 * makes it available from {@link #get()} (nullable) and {@link #obtain()} (null-safe). 027 * 028 * <p>A {@code SingletonSupplier} can be constructed via {@code of} factory methods 029 * or via constructors that provide a default supplier as a fallback. This is 030 * particularly useful for method reference suppliers, falling back to a default 031 * supplier for a method that returned {@code null} and caching the result. 032 * 033 * @author Juergen Hoeller 034 * @since 5.1 035 * @param <T> the type of results supplied by this supplier 036 */ 037public class SingletonSupplier<T> implements Supplier<T> { 038 039 @Nullable 040 private final Supplier<? extends T> instanceSupplier; 041 042 @Nullable 043 private final Supplier<? extends T> defaultSupplier; 044 045 @Nullable 046 private volatile T singletonInstance; 047 048 049 /** 050 * Build a {@code SingletonSupplier} with the given singleton instance 051 * and a default supplier for the case when the instance is {@code null}. 052 * @param instance the singleton instance (potentially {@code null}) 053 * @param defaultSupplier the default supplier as a fallback 054 */ 055 public SingletonSupplier(@Nullable T instance, Supplier<? extends T> defaultSupplier) { 056 this.instanceSupplier = null; 057 this.defaultSupplier = defaultSupplier; 058 this.singletonInstance = instance; 059 } 060 061 /** 062 * Build a {@code SingletonSupplier} with the given instance supplier 063 * and a default supplier for the case when the instance is {@code null}. 064 * @param instanceSupplier the immediate instance supplier 065 * @param defaultSupplier the default supplier as a fallback 066 */ 067 public SingletonSupplier(@Nullable Supplier<? extends T> instanceSupplier, Supplier<? extends T> defaultSupplier) { 068 this.instanceSupplier = instanceSupplier; 069 this.defaultSupplier = defaultSupplier; 070 } 071 072 private SingletonSupplier(Supplier<? extends T> supplier) { 073 this.instanceSupplier = supplier; 074 this.defaultSupplier = null; 075 } 076 077 private SingletonSupplier(T singletonInstance) { 078 this.instanceSupplier = null; 079 this.defaultSupplier = null; 080 this.singletonInstance = singletonInstance; 081 } 082 083 084 /** 085 * Get the shared singleton instance for this supplier. 086 * @return the singleton instance (or {@code null} if none) 087 */ 088 @Override 089 @Nullable 090 public T get() { 091 T instance = this.singletonInstance; 092 if (instance == null) { 093 synchronized (this) { 094 instance = this.singletonInstance; 095 if (instance == null) { 096 if (this.instanceSupplier != null) { 097 instance = this.instanceSupplier.get(); 098 } 099 if (instance == null && this.defaultSupplier != null) { 100 instance = this.defaultSupplier.get(); 101 } 102 this.singletonInstance = instance; 103 } 104 } 105 } 106 return instance; 107 } 108 109 /** 110 * Obtain the shared singleton instance for this supplier. 111 * @return the singleton instance (never {@code null}) 112 * @throws IllegalStateException in case of no instance 113 */ 114 public T obtain() { 115 T instance = get(); 116 Assert.state(instance != null, "No instance from Supplier"); 117 return instance; 118 } 119 120 121 /** 122 * Build a {@code SingletonSupplier} with the given singleton instance. 123 * @param instance the singleton instance (never {@code null}) 124 * @return the singleton supplier (never {@code null}) 125 */ 126 public static <T> SingletonSupplier<T> of(T instance) { 127 return new SingletonSupplier<>(instance); 128 } 129 130 /** 131 * Build a {@code SingletonSupplier} with the given singleton instance. 132 * @param instance the singleton instance (potentially {@code null}) 133 * @return the singleton supplier, or {@code null} if the instance was {@code null} 134 */ 135 @Nullable 136 public static <T> SingletonSupplier<T> ofNullable(@Nullable T instance) { 137 return (instance != null ? new SingletonSupplier<>(instance) : null); 138 } 139 140 /** 141 * Build a {@code SingletonSupplier} with the given supplier. 142 * @param supplier the instance supplier (never {@code null}) 143 * @return the singleton supplier (never {@code null}) 144 */ 145 public static <T> SingletonSupplier<T> of(Supplier<T> supplier) { 146 return new SingletonSupplier<>(supplier); 147 } 148 149 /** 150 * Build a {@code SingletonSupplier} with the given supplier. 151 * @param supplier the instance supplier (potentially {@code null}) 152 * @return the singleton supplier, or {@code null} if the instance supplier was {@code null} 153 */ 154 @Nullable 155 public static <T> SingletonSupplier<T> ofNullable(@Nullable Supplier<T> supplier) { 156 return (supplier != null ? new SingletonSupplier<>(supplier) : null); 157 } 158 159}