延迟加载器,cglib 的替代品?
Lazy loader, alternative to cglib?
借助 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(或任何其他 "light" 库)创建延迟加载代理?
您可以使用 Javassist 库 (http://www.javassist.org) ?
例如,Hibernate 大量使用 Javassist 代理来管理延迟加载:
https://docs.jboss.org/hibernate/orm/4.2/javadocs/org/hibernate/proxy/pojo/javassist/JavassistLazyInitializer.html
你可能会从中得到启发?
使用 Byte Buddy 会很容易,但如果您必须使用 "lightweight"(我的连接在不到 100 毫秒的时间内下载 3 MB),您可以这样做:
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 在模块系统方面面临着自己的问题,您可能需要在未来的某个时间进行另一次迁移。
好吧,正如@zapl 所建议的那样,这是完全没有任何第三方库的实现。我花了 3 分钟在 Eclispe 中创建这个:我创建了一个 class 存根,然后使用 '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();
}
}
借助 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(或任何其他 "light" 库)创建延迟加载代理?
您可以使用 Javassist 库 (http://www.javassist.org) ?
例如,Hibernate 大量使用 Javassist 代理来管理延迟加载: https://docs.jboss.org/hibernate/orm/4.2/javadocs/org/hibernate/proxy/pojo/javassist/JavassistLazyInitializer.html
你可能会从中得到启发?
使用 Byte Buddy 会很容易,但如果您必须使用 "lightweight"(我的连接在不到 100 毫秒的时间内下载 3 MB),您可以这样做:
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 在模块系统方面面临着自己的问题,您可能需要在未来的某个时间进行另一次迁移。
好吧,正如@zapl 所建议的那样,这是完全没有任何第三方库的实现。我花了 3 分钟在 Eclispe 中创建这个:我创建了一个 class 存根,然后使用 '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();
}
}