Ленивый загрузчик, альтернатива cglib? - PullRequest
0 голосов
/ 25 октября 2018

С помощью cglib я могу создать экземпляр BigInteger с отложенным созданием экземпляра, используя этот код:

Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(BigInteger.class);
enhancer.setCallback(
        new LazyLoader() {

            @Override
            public Object loadObject() throws Exception {
                // expensive computation here
                long totalCount = getTotalCount(totalCountExecutors); 
                return BigInteger.valueOf(totalCount);
            }
        });
totalCount =
        (BigInteger)
                enhancer.create(new Class[] {String.class}, new Object[] {"0"});

Однако вышеприведенное предупреждение выдает предупреждение с Java 11, и кажется, что в процессе его создания совместимый выпуск не создается, поэтому я бынравится мигрировать в другие библиотеки.ByteBuddy ... массивный, и хотел бы избежать такой большой зависимости.Можно ли создать ленивый загрузочный прокси с помощью javassist (или любой другой «легкой» библиотеки) вместо этого?

Ответы [ 3 ]

0 голосов
/ 31 октября 2018

Было бы легко с Byte Buddy, но если вы должны использовать «облегченный» (мое соединение загружает 3 МБ менее чем за 100 миллисекунд), то вот как вы это сделаете:

ProxyFactory factory = new ProxyFactory();
factory .setSuperclass(BigInteger.class);
factory .setFilter(new MethodFilter() {
  @Override
  public boolean isHandled(Method m) {
     return !m.getName().equals("finalize");
  }
});

Class<?> clazz = factory.createClass();
MethodHandler handler = new MethodHandler() {

  private volatile Object delegate;

  @Override
  public Object invoke(Object self, Method method, Method proceed,
                       Object[] args) throws Throwable {
     Object delegate = this.delegate;
     if (delegate == null) {
       synchronized (this) {
         delegate = this.delegate;
         if (delegate == null) {
           this.delegate = delegate = loadObject();
         }
       }
     }
     return method.invoke(delegate, args);
 }

  private Object loadObject() throws Exception {
    // expensive computation here
    long totalCount = getTotalCount(totalCountExecutors); 
    return BigInteger.valueOf(totalCount);
  }
};

BigInteger instance = (BigInteger) clazz.newInstance();
((Proxy) instance).setHandler(handler);

Сделайте однакообратите внимание, что Javassist сталкивается с собственными проблемами с модульной системой, и вам может понадобиться еще одна миграция в будущем.

0 голосов
/ 01 ноября 2018

Хорошо, вот реализация без какой-либо сторонней библиотеки, как предложено @zapl.Мне понадобилось 3 минуты, чтобы создать это в Eclispe: я создал заглушку класса, затем использовал «Generate Delegate Methods ...» и затем «Generate Getters and Setters ...».Все похвалы идут на @ zapl.

import java.math.BigInteger;

public class MyBigInt extends BigInteger {

    private BigInteger delegate;

    public MyBigInt() {
        super("0");
    }

    private BigInteger getDelegate() {
        if (delegate == null) {
            delegate = computeMeHere();
        }
        return delegate;
    }

    public byte byteValue() {
        return getDelegate().byteValue();
    }

    public short shortValue() {
        return getDelegate().shortValue();
    }

    public BigInteger nextProbablePrime() {
        return getDelegate().nextProbablePrime();
    }

    public BigInteger add(BigInteger val) {
        return getDelegate().add(val);
    }

    public BigInteger subtract(BigInteger val) {
        return getDelegate().subtract(val);
    }

    public BigInteger multiply(BigInteger val) {
        return getDelegate().multiply(val);
    }

    public BigInteger divide(BigInteger val) {
        return getDelegate().divide(val);
    }

    public BigInteger[] divideAndRemainder(BigInteger val) {
        return getDelegate().divideAndRemainder(val);
    }

    public BigInteger remainder(BigInteger val) {
        return getDelegate().remainder(val);
    }

    public BigInteger pow(int exponent) {
        return getDelegate().pow(exponent);
    }

    public BigInteger gcd(BigInteger val) {
        return getDelegate().gcd(val);
    }

    public BigInteger abs() {
        return getDelegate().abs();
    }

    public BigInteger negate() {
        return getDelegate().negate();
    }

    public int signum() {
        return getDelegate().signum();
    }

    public BigInteger mod(BigInteger m) {
        return getDelegate().mod(m);
    }

    public BigInteger modPow(BigInteger exponent, BigInteger m) {
        return getDelegate().modPow(exponent, m);
    }

    public BigInteger modInverse(BigInteger m) {
        return getDelegate().modInverse(m);
    }

    public BigInteger shiftLeft(int n) {
        return getDelegate().shiftLeft(n);
    }

    public BigInteger shiftRight(int n) {
        return getDelegate().shiftRight(n);
    }

    public BigInteger and(BigInteger val) {
        return getDelegate().and(val);
    }

    public BigInteger or(BigInteger val) {
        return getDelegate().or(val);
    }

    public BigInteger xor(BigInteger val) {
        return getDelegate().xor(val);
    }

    public BigInteger not() {
        return getDelegate().not();
    }

    public BigInteger andNot(BigInteger val) {
        return getDelegate().andNot(val);
    }

    public boolean testBit(int n) {
        return getDelegate().testBit(n);
    }

    public BigInteger setBit(int n) {
        return getDelegate().setBit(n);
    }

    public BigInteger clearBit(int n) {
        return getDelegate().clearBit(n);
    }

    public BigInteger flipBit(int n) {
        return getDelegate().flipBit(n);
    }

    public int getLowestSetBit() {
        return getDelegate().getLowestSetBit();
    }

    public int bitLength() {
        return getDelegate().bitLength();
    }

    public int bitCount() {
        return getDelegate().bitCount();
    }

    public boolean isProbablePrime(int certainty) {
        return getDelegate().isProbablePrime(certainty);
    }

    public int compareTo(BigInteger val) {
        return getDelegate().compareTo(val);
    }

    public boolean equals(Object x) {
        return getDelegate().equals(x);
    }

    public BigInteger min(BigInteger val) {
        return getDelegate().min(val);
    }

    public BigInteger max(BigInteger val) {
        return getDelegate().max(val);
    }

    public int hashCode() {
        return getDelegate().hashCode();
    }

    public String toString(int radix) {
        return getDelegate().toString(radix);
    }

    public String toString() {
        return getDelegate().toString();
    }

    public byte[] toByteArray() {
        return getDelegate().toByteArray();
    }

    public int intValue() {
        return getDelegate().intValue();
    }

    public long longValue() {
        return getDelegate().longValue();
    }

    public float floatValue() {
        return getDelegate().floatValue();
    }

    public double doubleValue() {
        return getDelegate().doubleValue();
    }

    public long longValueExact() {
        return getDelegate().longValueExact();
    }

    public int intValueExact() {
        return getDelegate().intValueExact();
    }

    public short shortValueExact() {
        return getDelegate().shortValueExact();
    }

    public byte byteValueExact() {
        return getDelegate().byteValueExact();
    }
}
0 голосов
/ 30 октября 2018

Вы можете использовать библиотеку Javassist (http://www.javassist.org)?

Например, Hibernate интенсивно использует прокси-серверы Javassist для управления отложенной загрузкой: https://docs.jboss.org/hibernate/orm/4.2/javadocs/org/hibernate/proxy/pojo/javassist/JavassistLazyInitializer.html

Вы могли бы вдохновить их?

...