如何使用 LambdaMetaFactory 在运行时创建代理对象?
How to create proxy object at runtime using LambdaMetaFactory?
如何使用 LambdaMetaFactory
为 SAM/functional 接口创建代理对象
即。相当于
public static Object java.lang.reflect.Proxy.newProxyInstance(ClassLoader, Class<?>[], InvocationHandler)
例如。我有多个工厂接口
interface X{
// members
// methods
}
interface Y{
// members
// methods
}
public interface Factory1{
X get(String name);
}
public interface Factory2{
Y get(String name);
}
.
.
.
public interface FactoryN{
someclassOrInterface get(String name);
}
并且我想在运行时生成绑定到一些预构建 bean 容器的工厂代理
例如
public Object getFactoryBean(String name){
return beanContainer.get(name);
}
类似于
org.springframework.beans.factory.config.ServiceLocatorFactoryBean
但建立在 LambdaMetaFactory 之上。我尝试了以下代码但出现异常
static <T> T getFactory(Class<T> factoryClass) {
T factory =null;
try {
final MethodHandles.Lookup lookup = MethodHandles.lookup();
Class<?> beanType = factoryClass.getMethod("get", String.class).getReturnType();
final CallSite site = LambdaMetafactory.metafactory(lookup,
"get",
MethodType.methodType(factoryClass, String.class),
MethodType.methodType(beanType),
lookup.findStatic(ReflectionUtil.class, "getFactoryBean", MethodType.methodType(Object.class, String.class)),
MethodType.methodType(beanType));
factory = (T) site.getTarget().invoke();
} catch(Throwable e) {
e.printStackTrace();
}
return factory;
}
public static Object getFactoryBean(String beanName) {
return beanMap.get(beanName);
}
java.lang.invoke.WrongMethodTypeException: cannot convert MethodHandle(String)Factory1 to ()Object
at java.lang.invoke.MethodHandle.asTypeUncached(MethodHandle.java:775)
at java.lang.invoke.MethodHandle.asType(MethodHandle.java:761)
at java.lang.invoke.Invokers.checkGenericType(Invokers.java:321)
提前致谢。
您的代码为 invokedType
参数指定了 String
参数,而不是 samMethodType
和 instantiatedMethodType
参数。如果您想 捕获 一个 String
值并实现不带参数的功能签名,这将是正确的做法。
但是您始终显示带有 String
参数的接口并在不带参数的情况下调用 invoke()
。因此,代码应该看起来像
static <T> T getFactory(Class<T> factoryClass) {
T factory =null;
try {
final MethodHandles.Lookup lookup = MethodHandles.lookup();
Class<?> beanType = factoryClass.getMethod("get", String.class).getReturnType();
final CallSite site = LambdaMetafactory.metafactory(lookup,
"get",
MethodType.methodType(factoryClass),
MethodType.methodType(beanType, String.class),
lookup.findStatic(ReflectionUtil.class, "getFactoryBean",
MethodType.methodType(Object.class, String.class)),
MethodType.methodType(beanType, String.class));
factory = (T)site.getTarget().invoke();
} catch(Throwable e) {
e.printStackTrace();
}
return factory;
}
可以简化为
static <T> T getFactory(Class<T> factoryClass) {
try {
MethodHandles.Lookup lookup = MethodHandles.lookup();
Class<?> beanType = factoryClass.getMethod("get", String.class).getReturnType();
MethodHandle target = lookup.findStatic(ReflectionUtil.class, "getFactoryBean",
MethodType.methodType(Object.class, String.class));
MethodType funcType = target.type().changeReturnType(beanType);
return (T)LambdaMetafactory.metafactory(
lookup, "get", MethodType.methodType(factoryClass), funcType, target, funcType)
.getTarget().invoke();
} catch(Throwable e) {
e.printStackTrace();
return null; // rethink this error handling
}
}
如何使用 LambdaMetaFactory
为 SAM/functional 接口创建代理对象即。相当于
public static Object java.lang.reflect.Proxy.newProxyInstance(ClassLoader, Class<?>[], InvocationHandler)
例如。我有多个工厂接口
interface X{
// members
// methods
}
interface Y{
// members
// methods
}
public interface Factory1{
X get(String name);
}
public interface Factory2{
Y get(String name);
}
.
.
.
public interface FactoryN{
someclassOrInterface get(String name);
}
并且我想在运行时生成绑定到一些预构建 bean 容器的工厂代理 例如
public Object getFactoryBean(String name){
return beanContainer.get(name);
}
类似于
org.springframework.beans.factory.config.ServiceLocatorFactoryBean
但建立在 LambdaMetaFactory 之上。我尝试了以下代码但出现异常
static <T> T getFactory(Class<T> factoryClass) {
T factory =null;
try {
final MethodHandles.Lookup lookup = MethodHandles.lookup();
Class<?> beanType = factoryClass.getMethod("get", String.class).getReturnType();
final CallSite site = LambdaMetafactory.metafactory(lookup,
"get",
MethodType.methodType(factoryClass, String.class),
MethodType.methodType(beanType),
lookup.findStatic(ReflectionUtil.class, "getFactoryBean", MethodType.methodType(Object.class, String.class)),
MethodType.methodType(beanType));
factory = (T) site.getTarget().invoke();
} catch(Throwable e) {
e.printStackTrace();
}
return factory;
}
public static Object getFactoryBean(String beanName) {
return beanMap.get(beanName);
}
java.lang.invoke.WrongMethodTypeException: cannot convert MethodHandle(String)Factory1 to ()Object
at java.lang.invoke.MethodHandle.asTypeUncached(MethodHandle.java:775)
at java.lang.invoke.MethodHandle.asType(MethodHandle.java:761)
at java.lang.invoke.Invokers.checkGenericType(Invokers.java:321)
提前致谢。
您的代码为 invokedType
参数指定了 String
参数,而不是 samMethodType
和 instantiatedMethodType
参数。如果您想 捕获 一个 String
值并实现不带参数的功能签名,这将是正确的做法。
但是您始终显示带有 String
参数的接口并在不带参数的情况下调用 invoke()
。因此,代码应该看起来像
static <T> T getFactory(Class<T> factoryClass) {
T factory =null;
try {
final MethodHandles.Lookup lookup = MethodHandles.lookup();
Class<?> beanType = factoryClass.getMethod("get", String.class).getReturnType();
final CallSite site = LambdaMetafactory.metafactory(lookup,
"get",
MethodType.methodType(factoryClass),
MethodType.methodType(beanType, String.class),
lookup.findStatic(ReflectionUtil.class, "getFactoryBean",
MethodType.methodType(Object.class, String.class)),
MethodType.methodType(beanType, String.class));
factory = (T)site.getTarget().invoke();
} catch(Throwable e) {
e.printStackTrace();
}
return factory;
}
可以简化为
static <T> T getFactory(Class<T> factoryClass) {
try {
MethodHandles.Lookup lookup = MethodHandles.lookup();
Class<?> beanType = factoryClass.getMethod("get", String.class).getReturnType();
MethodHandle target = lookup.findStatic(ReflectionUtil.class, "getFactoryBean",
MethodType.methodType(Object.class, String.class));
MethodType funcType = target.type().changeReturnType(beanType);
return (T)LambdaMetafactory.metafactory(
lookup, "get", MethodType.methodType(factoryClass), funcType, target, funcType)
.getTarget().invoke();
} catch(Throwable e) {
e.printStackTrace();
return null; // rethink this error handling
}
}