在CDI 1.2中,有一种方法可以检查类实例是否被代理?我需要这个,因为我需要获取原始类的名称,而不是代理名称。
@Inject Bean bean;
public void sysout() {
// will print something like com.Bean$$Weld9239823
System.out.println(bean.getClass());
// I don't know how to check if the bean instance if a proxy or real class instance
}
使用Weld类我可以完成这项工作:
public void sysout() {
// will print true because this is a proxy
System.out.println(ProxyObject.class.isAssignableFrom(bean));
// will print com.Bean
System.out.println(((TargetInstanceProxy) bean).getTargetInstance());
}
在CDI 1.1中,没有办法做到这一点。如果添加了关于此的方法,我会在CDI 1.2文档中搜索,但我找不到任何内容。
所以......我想念一些东西和CDI 1.2有一种获取原始类名和实例的方法吗?或者如果没有,可以在近似功能中添加此功能吗?
答案 0 :(得分:2)
对于WildFly上的Weld,请执行以下操作:
public boolean isProxy(Object obj) {
try{
return Class.forName("org.jboss.weld.bean.proxy.ProxyObject").isInstance(obj);
} catch (Exception e) {
log.error("Unable to check if object is proxy", e);
}
return false;
}
要检索实际对象而不是代理(我需要序列化它)我这样做:
public Object getObject(Object obj) {
Field f = null;
boolean isAccessible = false;
try {
for(Field fi : Class.forName(handler).getDeclaredFields()) {
if(fi.getName().equals(field)) {
f = fi;
isAccessible = f.isAccessible();
f.setAccessible(true);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
if(f == null) {
throw new RuntimeException(new NoSuchFieldException(String.format(
"The required field '%s' not found in '%s'. " +
"May be the code is obsolete for running on this application server.",
field, method)));
} else {
try{
obj = f.get(getHandler(obj));
for(Method m : Class.forName(instance).getMethods()) {
if(m.getName().equals(value)) {
return m.invoke(obj);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
f.setAccessible(isAccessible);
}
throw new NoSuchMethodError(String.format(
"The required method '%s' not found in '%s'. " +
"May be the code is obsolete for running on this application server.",
value, instance));
}
}
请注意,它是尽可能最黑暗的魔法,性能非常差,并且可以在任何WildFly更新时中断,如果它们更改了类中的字段,方法。
答案 1 :(得分:0)
这是一个可怕的黑客,但对于Weld(可能还有其他实现),您可以检查类名是否包含"代理":possibleProxy.getClass().getSimpleName().contains("Proxy")
。我仅将其用于记录目的,以获取已包装类名的清理版本:
/**
* Get the actual simple name of the objects class that might be wrapped by
* a proxy. A "simple" class name is not fully qualified (no package name).
*
* @param possibleProxy an object that might be a proxy to the actual
* object.
* @return the simple name of the actual object's class
*/
public static String getActualSimpleClassName(final Object possibleProxy) {
final String outerClassName = possibleProxy.getClass().getSimpleName();
final String innerClassName;
if (outerClassName.contains("Proxy")) {
innerClassName = outerClassName.substring(0, outerClassName.indexOf('$'));
} else {
innerClassName = outerClassName;
}
return innerClassName;
}
答案 2 :(得分:0)
您可以在代理的cdi bean中创建一个方法,如
public String getClassName() {
return this.getClass().getName();
}
这不是最好的解决方案,而是通过代理获取类名的一种简单实用的方法......这样做的缺点是方法必须在每个实现上......