设计模式——享元模式(Flyweight Pattern)+ Spring相关源码

文章目录

一、享元模式定义

类型: 结构型模式
介绍: 使用容器(数组、集合等...)缓存常用对象。它也是池技术的重要实现方式,正如常量池、数据库连接池、缓冲池等都是享元模式的应用。
目的: 主要用于减少 频繁创建对象带来的开销。

二、例子

2.1 菜鸟教程例子

2.1.1 定义被缓存对象

java 复制代码
public class Circle {
   private String color;
 
   public Circle(String color){
      this.color = color;     
   }
   public void draw() {
      System.out.println("Circle: Draw()");
   }
}

2.1.2 定义ShapeFactory

ShapeFactory用HashMap缓存Circle对象。

java 复制代码
import java.util.HashMap;
 
public class ShapeFactory {
   private static final HashMap<String, Shape> circleMap = new HashMap<>();
 
   public static Shape getCircle(String color) {
      Circle circle = (Circle)circleMap.get(color);
 
      if(circle == null) {
         circle = new Circle(color);
         circleMap.put(color, circle);
         System.out.println("Creating circle of color : " + color);
      }
      return circle;
   }
}

2.2 JDK源码------Integer

-128~127会去IntegerCache里获取

java 复制代码
public final class Integer extends Number implements Comparable<Integer>, Constable, ConstantDesc {

	@IntrinsicCandidate
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

}

缓存池IntegerCache

java 复制代码
private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer[] cache;
    static Integer[] archivedCache;

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                h = Math.max(parseInt(integerCacheHighPropValue), 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

        // Load IntegerCache.archivedCache from archive, if possible
        CDS.initializeFromArchive(IntegerCache.class);
        int size = (high - low) + 1;

        // Use the archived cache if it exists and is large enough
        if (archivedCache == null || size > archivedCache.length) {
            Integer[] c = new Integer[size];
            int j = low;
            for(int i = 0; i < c.length; i++) {
                c[i] = new Integer(j++);
            }
            archivedCache = c;
        }
        cache = archivedCache;
        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}

2.3 JDK源码------DriverManager

CopyOnWriteArrayList registeredDrivers 缓存DriverInfo对象。

java 复制代码
public class DriverManager {


    // List of registered JDBC drivers
    private static final CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
    
	public static Connection getConnection(String url, java.util.Properties info) throws SQLException {
        return (getConnection(url, info, Reflection.getCallerClass()));
    }
	
	 @CallerSensitiveAdapter
    private static Connection getConnection(
        String url, java.util.Properties info, Class<?> caller) throws SQLException {
        /*
         * When callerCl is null, we should check the application's
         * (which is invoking this class indirectly)
         * classloader, so that the JDBC driver class outside rt.jar
         * can be loaded from here.
         */
        ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
        if (callerCL == null || callerCL == ClassLoader.getPlatformClassLoader()) {
            callerCL = Thread.currentThread().getContextClassLoader();
        }

        if (url == null) {
            throw new SQLException("The url cannot be null", "08001");
        }

        println("DriverManager.getConnection(\"" + url + "\")");

        ensureDriversInitialized();

        // Walk through the loaded registeredDrivers attempting to make a connection.
        // Remember the first exception that gets raised so we can reraise it.
        SQLException reason = null;

        for (DriverInfo aDriver : registeredDrivers) {
            // If the caller does not have permission to load the driver then
            // skip it.
            if (isDriverAllowed(aDriver.driver, callerCL)) {
                try {
                    println("    trying " + aDriver.driver.getClass().getName());
                    Connection con = aDriver.driver.connect(url, info);
                    if (con != null) {
                        // Success!
                        println("getConnection returning " + aDriver.driver.getClass().getName());
                        return (con);
                    }
                } catch (SQLException ex) {
                    if (reason == null) {
                        reason = ex;
                    }
                }

            } else {
                println("    skipping: " + aDriver.driver.getClass().getName());
            }

        }

        // if we got here nobody could connect.
        if (reason != null)    {
            println("getConnection failed: " + reason);
            throw reason;
        }

        println("getConnection: no suitable driver found for "+ url);
        throw new SQLException("No suitable driver found for "+ url, "08001");
    }

}
 

2.4 Spring源码------HandlerMethodArgumentResolverComposite

java 复制代码
public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {

   private final List<HandlerMethodArgumentResolver> argumentResolvers = new LinkedList<>();

   private final Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache = new ConcurrentHashMap<>(256);
   
    @Nullable
    private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
        HandlerMethodArgumentResolver result = (HandlerMethodArgumentResolver)this.argumentResolverCache.get(parameter);
        if (result == null) {
            Iterator var3 = this.argumentResolvers.iterator();

            while(var3.hasNext()) {
                HandlerMethodArgumentResolver resolver = (HandlerMethodArgumentResolver)var3.next();
                if (resolver.supportsParameter(parameter)) {
                    result = resolver;
                    this.argumentResolverCache.put(parameter, resolver);
                    break;
                }
            }
        }

        return result;
    }
}

除此之外BeanFactory获取bean其实也是一种享元模式的应用。

三、其他设计模式

创建型模式
结构型模式

行为型模式

相关推荐
Andya_net5 小时前
Spring | @EventListener事件机制深度解析
java·后端·spring
Java面试题总结7 小时前
Spring @Validated失效?原因、排查与高效解决方案全解析
java·spring boot·spring
开longlong了吗?8 小时前
Luan Takeaway——大模型驱动的智能外卖管理系统( Spring Cloud、Langchain4j )
后端·spring·spring cloud·langchain
xu_ws10 小时前
Spring-ai项目-deepseek-6-哄哄模拟器
java·人工智能·spring
刘 大 望10 小时前
SpringAI Tool Calling(工具调用)
java·spring boot·spring·ai·maven·intellij-idea·文心一言
Je1lyfish13 小时前
CMU15-445 (2026 Spring) Project#2 - B+ Tree
linux·数据结构·数据库·c++·sql·spring·oracle
生产队队长13 小时前
SpringBoot3:ApplicationAvailability监控应用程序可用性状态[官方文档]
java·spring·mybatis
leikooo14 小时前
在 Spring AI 中自定义 Tool 调用返回值——实现 TodoList 提醒注入
spring
码喽7号15 小时前
Springboot学习五:MybatisPlus的快速上手
spring boot·学习·spring
weixin_7042660515 小时前
事务管理全解析:从ACID到Spring实现
java·数据库·spring