1    享元模式源码解析

1.1  享元模式源码解析1(jdk中的应用)

1.2  享元模式源码解析2(tomcat中的应用)

 

 

1    享元模式源码解析
1.1  享元模式源码解析1(jdk中的应用)

测试类:

package com.geely.design.pattern.structural.flyweight;

public class Test2 {
    public static void main(String [] args){
        Integer a = 100;
        Integer b = Integer.valueOf(100);
        System.out.println("a==b"+ (a==b));

        Integer c = 1000;
        Integer d = Integer.valueOf(1000);
        System.out.println("c==d"+ (c==d));
    }
}

 

Integer类:

public final class Integer extends Number implements Comparable<Integer> {

 /**
     * Returns an {@code Integer} instance representing the specified
     * {@code int} value.  If a new {@code Integer} instance is not
     * required, this method should generally be used in preference to
     * the constructor {@link #Integer(int)}, as this method is likely
     * to yield significantly better space and time performance by
     * caching frequently requested values.
     *
     * This method will always cache values in the range -128 to 127,
     * inclusive, and may cache other values outside of this range.
     * 如果传入的数值在缓存的-127和128之间,那么都会在cache中,否则的话,会new出新的对象,这也是为什么100==100为true,1000==1000为false
     *  test中a,b,c,d都执行了该方法,一共执行了4次   。
*
@param i an {@code int} value. * @return an {@code Integer} instance representing {@code i}. * @since 1.5 */ public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } /** * Cache to support the object identity semantics of autoboxing for values between * -128 and 127 (inclusive) as required by JLS. * * The cache is initialized on first usage. The size of the cache * may be controlled by the -XX:AutoBoxCacheMax=<size> option. * During VM initialization, java.lang.Integer.IntegerCache.high property * may be set and saved in the private system properties in the * sun.misc.VM class. */ private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); } private IntegerCache() {} } }

 

打印日志:

"C:\Program Files\Java\jdk1.7.0_79\bin\java.exe" -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:63738,suspend=y,server=n -javaagent:C:\Users\weijingli\AppData\Local\Temp\capture1jars\debugger-agent.jar=file:/C:/Users/weijingli/AppData/Local/Temp/capture.props -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_79\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\rt.jar;F:\xiangmu3\Xin\Idea\design_pattern\target\classes;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\apache\tomcat\tomcat-servlet-api\7.0.64\tomcat-servlet-api-7.0.64.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\springframework\session\spring-session-core\2.1.7.RELEASE\spring-session-core-2.1.7.RELEASE.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\springframework\spring-webmvc\4.0.3.RELEASE\spring-webmvc-4.0.3.RELEASE.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\springframework\spring-beans\4.0.3.RELEASE\spring-beans-4.0.3.RELEASE.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\springframework\spring-context\4.0.3.RELEASE\spring-context-4.0.3.RELEASE.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\springframework\spring-aop\4.0.3.RELEASE\spring-aop-4.0.3.RELEASE.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\aopalliance\aopalliance\1.0\aopalliance-1.0.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\springframework\spring-core\4.0.3.RELEASE\spring-core-4.0.3.RELEASE.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\springframework\spring-expression\4.0.3.RELEASE\spring-expression-4.0.3.RELEASE.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\springframework\spring-web\4.0.3.RELEASE\spring-web-4.0.3.RELEASE.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\springframework\spring-oxm\4.0.3.RELEASE\spring-oxm-4.0.3.RELEASE.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\springframework\spring-jdbc\4.0.3.RELEASE\spring-jdbc-4.0.3.RELEASE.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\springframework\spring-tx\4.0.3.RELEASE\spring-tx-4.0.3.RELEASE.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\springframework\spring-test\4.0.3.RELEASE\spring-test-4.0.3.RELEASE.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\aspectj\aspectjweaver\1.7.3\aspectjweaver-1.7.3.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\mybatis\mybatis-spring\1.3.0\mybatis-spring-1.3.0.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\mybatis\mybatis\3.4.1\mybatis-3.4.1.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\aspectj\aspectjrt\1.6.11\aspectjrt-1.6.11.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\codehaus\jackson\jackson-mapper-asl\1.9.12\jackson-mapper-asl-1.9.12.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\codehaus\jackson\jackson-core-asl\1.9.12\jackson-core-asl-1.9.12.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\commons-dbcp\commons-dbcp\1.4\commons-dbcp-1.4.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\commons-pool\commons-pool\1.5.4\commons-pool-1.5.4.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\ch\qos\logback\logback-classic\1.1.2\logback-classic-1.1.2.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\slf4j\slf4j-api\1.7.6\slf4j-api-1.7.6.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\ch\qos\logback\logback-core\1.1.2\logback-core-1.1.2.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\mysql\mysql-connector-java\5.1.6\mysql-connector-java-5.1.6.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\com\google\guava\guava\20.0\guava-20.0.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\apache\commons\commons-lang3\3.5\commons-lang3-3.5.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\commons-collections\commons-collections\3.2.1\commons-collections-3.2.1.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\junit\junit\4.12\junit-4.12.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\joda-time\joda-time\2.3\joda-time-2.3.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\hashids\hashids\1.0.1\hashids-1.0.1.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\commons-net\commons-net\3.1\commons-net-3.1.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\commons-fileupload\commons-fileupload\1.2.2\commons-fileupload-1.2.2.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\commons-io\commons-io\2.0.1\commons-io-2.0.1.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\com\github\pagehelper\pagehelper\4.1.0\pagehelper-4.1.0.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\com\github\miemiedev\mybatis-paginator\1.2.17\mybatis-paginator-1.2.17.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\com\github\jsqlparser\jsqlparser\0.9.4\jsqlparser-0.9.4.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\commons-codec\commons-codec\1.10\commons-codec-1.10.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\commons-configuration\commons-configuration\1.10\commons-configuration-1.10.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\commons-lang\commons-lang\2.6\commons-lang-2.6.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\commons-logging\commons-logging\1.1.1\commons-logging-1.1.1.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\com\google\zxing\core\2.1\core-2.1.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\com\google\code\gson\gson\2.3.1\gson-2.3.1.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\redis\clients\jedis\2.6.0\jedis-2.6.0.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\apache\commons\commons-pool2\2.0\commons-pool2-2.0.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\projectlombok\lombok\1.16.18\lombok-1.16.18.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\redisson\redisson\2.9.0\redisson-2.9.0.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\io\netty\netty-common\4.1.8.Final\netty-common-4.1.8.Final.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\io\netty\netty-codec\4.1.8.Final\netty-codec-4.1.8.Final.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\io\netty\netty-buffer\4.1.8.Final\netty-buffer-4.1.8.Final.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\io\netty\netty-transport\4.1.8.Final\netty-transport-4.1.8.Final.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\io\netty\netty-resolver\4.1.8.Final\netty-resolver-4.1.8.Final.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\io\netty\netty-handler\4.1.8.Final\netty-handler-4.1.8.Final.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\javax\cache\cache-api\1.0.0\cache-api-1.0.0.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\io\projectreactor\reactor-stream\2.0.8.RELEASE\reactor-stream-2.0.8.RELEASE.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\io\projectreactor\reactor-core\2.0.8.RELEASE\reactor-core-2.0.8.RELEASE.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\reactivestreams\reactive-streams\1.0.0\reactive-streams-1.0.0.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\com\fasterxml\jackson\dataformat\jackson-dataformat-yaml\2.6.7\jackson-dataformat-yaml-2.6.7.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\yaml\snakeyaml\1.15\snakeyaml-1.15.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\com\fasterxml\jackson\core\jackson-core\2.6.7\jackson-core-2.6.7.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\com\fasterxml\jackson\core\jackson-databind\2.6.7\jackson-databind-2.6.7.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\com\fasterxml\jackson\dataformat\jackson-dataformat-avro\2.9.0\jackson-dataformat-avro-2.9.0.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\com\fasterxml\jackson\core\jackson-annotations\2.9.0\jackson-annotations-2.9.0.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\apache\avro\avro\1.8.1\avro-1.8.1.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\com\thoughtworks\paranamer\paranamer\2.7\paranamer-2.7.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\xerial\snappy\snappy-java\1.1.1.3\snappy-java-1.1.1.3.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\apache\commons\commons-compress\1.8.1\commons-compress-1.8.1.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\org\tukaani\xz\1.5\xz-1.5.jar;F:\xiangmu3\Xin\FuQiang\maven\code\repo\com\sun\faces\jsf-api\1.2\jsf-api-1.2.jar;D:\java\devolopKit\idea\anZh\IntelliJ IDEA Community Edition 2018.1.4\lib\idea_rt.jar" com.geely.design.pattern.structural.flyweight.Test2
Connected to the target VM, address: '127.0.0.1:63738', transport: 'socket'
a==btrue
c==dfalse
Disconnected from the target VM, address: '127.0.0.1:63738', transport: 'socket'

Process finished with exit code 0

 

 

1.2  享元模式源码解析2(tomcat中的应用)

父类(GenericObjectPoolConfig):添加了一些默认的配置

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.apache.commons.pool2.impl;

public class GenericObjectPoolConfig extends BaseObjectPoolConfig {
    public static final int DEFAULT_MAX_TOTAL = 8;
    public static final int DEFAULT_MAX_IDLE = 8;
    public static final int DEFAULT_MIN_IDLE = 0;
    private int maxTotal = 8;
    private int maxIdle = 8;
    private int minIdle = 0;

    public GenericObjectPoolConfig() {
    }

    public int getMaxTotal() {
        return this.maxTotal;
    }

    public void setMaxTotal(int maxTotal) {
        this.maxTotal = maxTotal;
    }

    public int getMaxIdle() {
        return this.maxIdle;
    }

    public void setMaxIdle(int maxIdle) {
        this.maxIdle = maxIdle;
    }

    public int getMinIdle() {
        return this.minIdle;
    }

    public void setMinIdle(int minIdle) {
        this.minIdle = minIdle;
    }

    public GenericObjectPoolConfig clone() {
        try {
            return (GenericObjectPoolConfig)super.clone();
        } catch (CloneNotSupportedException var2) {
            throw new AssertionError();
        }
    }
}

 

子类(GenericKeyedObjectPoolConfig)(选2版本):

通过object的双端队列来保存对象池的对象,重点看p是怎么给值的。

/**
   *     借
   */
 public T borrowObject(K key, long borrowMaxWaitMillis) throws Exception {
        this.assertOpen();
        PooledObject<T> p = null;
        boolean blockWhenExhausted = this.getBlockWhenExhausted();
        long waitTime = 0L;
        GenericKeyedObjectPool.ObjectDeque objectDeque = this.register(key);

        try {
            while(p == null) {
                boolean create = false;
                if (blockWhenExhausted) {
                    p = (PooledObject)objectDeque.getIdleObjects().pollFirst();
                    if (p == null) {
                        create = true;
                        p = this.create(key);
                    }

                    if (p == null) {
                        if (borrowMaxWaitMillis < 0L) {
                            p = (PooledObject)objectDeque.getIdleObjects().takeFirst();
                        } else {
                            waitTime = System.currentTimeMillis();
                            p = (PooledObject)objectDeque.getIdleObjects().pollFirst(borrowMaxWaitMillis, TimeUnit.MILLISECONDS);
                            waitTime = System.currentTimeMillis() - waitTime;
                        }
                    }

                    if (p == null) {
                        throw new NoSuchElementException("Timeout waiting for idle object");
                    }

                    if (!p.allocate()) {
                        p = null;
                    }
                } else {
                    p = (PooledObject)objectDeque.getIdleObjects().pollFirst();
                    if (p == null) {
                        create = true;
                        p = this.create(key);
                    }

                    if (p == null) {
                        throw new NoSuchElementException("Pool exhausted");
                    }

                    if (!p.allocate()) {
                        p = null;
                    }
                }

                if (p != null) {
                    try {
                        this.factory.activateObject(key, p);
                    } catch (Exception var22) {
                        try {
                            this.destroy(key, p, true);
                        } catch (Exception var21) {
                            ;
                        }

                        p = null;
                        if (create) {
                            NoSuchElementException nsee = new NoSuchElementException("Unable to activate object");
                            nsee.initCause(var22);
                            throw nsee;
                        }
                    }

                    if (p != null && this.getTestOnBorrow()) {
                        boolean validate = false;
                        Throwable validationThrowable = null;

                        try {
                            validate = this.factory.validateObject(key, p);
                        } catch (Throwable var20) {
                            PoolUtils.checkRethrow(var20);
                            validationThrowable = var20;
                        }

                        if (!validate) {
                            try {
                                this.destroy(key, p, true);
                                this.destroyedByBorrowValidationCount.incrementAndGet();
                            } catch (Exception var19) {
                                ;
                            }

                            p = null;
                            if (create) {
                                NoSuchElementException nsee = new NoSuchElementException("Unable to validate object");
                                nsee.initCause(validationThrowable);
                                throw nsee;
                            }
                        }
                    }
                }
            }
        } finally {
            this.deregister(key);
        }

        this.updateStatsBorrow(p, waitTime);
        return p.getObject();
    }


/**
   *     还
   */
  public void returnObject(K key, T obj) {
        GenericKeyedObjectPool<K, T>.ObjectDeque<T> objectDeque = (GenericKeyedObjectPool.ObjectDeque)this.poolMap.get(key);
        PooledObject<T> p = (PooledObject)objectDeque.getAllObjects().get(obj);
        if (p == null) {
            throw new IllegalStateException("Returned object not currently part of this pool");
        } else {
            long activeTime = p.getActiveTimeMillis();
            if (this.getTestOnReturn() && !this.factory.validateObject(key, p)) {
                try {
                    this.destroy(key, p, true);
                } catch (Exception var11) {
                    this.swallowException(var11);
                }

                this.updateStatsReturn(activeTime);
            } else {
                try {
                    this.factory.passivateObject(key, p);
                } catch (Exception var13) {
                    this.swallowException(var13);

                    try {
                        this.destroy(key, p, true);
                    } catch (Exception var10) {
                        this.swallowException(var10);
                    }

                    this.updateStatsReturn(activeTime);
                    return;
                }

                if (!p.deallocate()) {
                    throw new IllegalStateException("Object has already been retured to this pool");
                } else {
                    int maxIdle = this.getMaxIdlePerKey();
                    LinkedBlockingDeque<PooledObject<T>> idleObjects = objectDeque.getIdleObjects();
                    if (this.isClosed() || maxIdle > -1 && maxIdle <= idleObjects.size()) {
                        try {
                            this.destroy(key, p, true);
                        } catch (Exception var12) {
                            this.swallowException(var12);
                        }
                    } else if (this.getLifo()) {
                        idleObjects.addFirst(p);
                    } else {
                        idleObjects.addLast(p);
                    }

                    if (this.hasBorrowWaiters()) {
                        this.reuseCapacity();
                    }

                    this.updateStatsReturn(activeTime);
                }
            }
        }
    }

 

工厂类:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.apache.commons.pool2;

public interface KeyedPooledObjectFactory<K, V> {
   //创建对象方法
    PooledObject<V> makeObject(K var1) throws Exception;

  //销毁对象方法
    void destroyObject(K var1, PooledObject<V> var2) throws Exception;

  //验证对象方法
    boolean validateObject(K var1, PooledObject<V> var2);
  //激活对象方法,用的时候激活
    void activateObject(K var1, PooledObject<V> var2) throws Exception;
  //钝化对象方法,不用的钝化
    void passivateObject(K var1, PooledObject<V> var2) throws Exception;
}

 

posted on 2019-09-14 15:33  菜鸟乙  阅读(222)  评论(0编辑  收藏  举报