使用 ByteBuddy 代理的 Hibernate 中的 MethodHandler 陷入无限循环
MethodHandler in Hibernate using ByteBuddy proxies gets stuck in endless loop
我目前正在为 Hibernate 迁移一个旧工具,以根据实体统计信息自动进行预取。旧工具使用 Hibernate 3.1,因此还有一些工作要做。传统上,Hibernate 使用 CGlib 代理,但在我为最新版本的 Hibernate 开发时,我将代理生成更改为 ByteBuddy。
但是,自从更改为 ByteBuddy 后,我在让 MethodHandler 工作方面遇到了一些问题。我的工具中的方法处理程序应该处理所有对代理的调用,以收集必要的统计信息。目前,我的方法处理程序如下所示:
public class EntityProxyMethodHandler implements ProxyConfiguration.Interceptor, Serializable {
private final EntityTracker entityTracker;
private final Object proxiedObject;
private final String proxiedClassName;
EntityProxyMethodHandler(
Object proxiedObject,
String proxiedClassName,
Set<Property> persistentProperties,
ExtentManager extentManager) {
this.proxiedObject = proxiedObject;
this.proxiedClassName = proxiedClassName;
this.entityTracker = new EntityTracker(persistentProperties, extentManager );
}
@Override
@RuntimeType
public Object intercept(@This Object instance, @Origin Method method, @AllArguments Object[] arguments)
throws Exception {
final String methodName = method.getName();
if ( "toString".equals( methodName ) ) {
return proxiedClassName + "@" + System.identityHashCode( instance );
}
else if ( "equals".equals( methodName ) ) {
return proxiedObject == instance;
}
else if ( "hashCode".equals( methodName ) ) {
return System.identityHashCode( instance );
}
else if ( arguments.length == 0 ) {
switch ( methodName ) {
case "disableTracking": {
boolean oldValue = entityTracker.isTracking();
entityTracker.setTracking( false );
return oldValue;
}
case "enableTracking": {
boolean oldValue = entityTracker.isTracking();
entityTracker.setTracking( true );
return oldValue;
}
case "isAccessed":
return entityTracker.isAccessed();
default:
break;
}
}
else if ( arguments.length == 1 ) {
if ( methodName.equals( "addTracker" ) && method.getParameterTypes()[0].equals( Statistics.class ) ) {
entityTracker.addTracker( (Statistics) arguments[0] );
return null;
}
else if ( methodName.equals( "addTrackers" ) && method.getParameterTypes()[0].equals( Set.class ) ) {
@SuppressWarnings("unchecked")
Set<Statistics> newTrackers = (Set) arguments[0];
entityTracker.addTrackers( newTrackers );
return null;
}
else if ( methodName
.equals( "extendProfile" ) && method.getParameterTypes()[0].equals( Statistics.class ) ) {
entityTracker.extendProfile( (Statistics) arguments[0], instance );
return null;
}
else if ( methodName
.equals( "removeTracker" ) && method.getParameterTypes()[0].equals( Statistics.class ) ) {
entityTracker.removeTracker( (Statistics) arguments[0] );
return null;
}
}
entityTracker.trackAccess( instance );
return method.invoke( instance, arguments ); // Gets stuck here, the method interception gets intercepted endlessly
}
代理工厂看起来像这样:
public class EntityProxyFactory {
private static SessionFactoryImplementor sessionFactory = AutofetchIntegrator.getSessionFactory();
private static final ConcurrentMap<Class<?>, Constructor<?>> entityConstructorMap = new ConcurrentHashMap<>();
private static <T> Constructor<T> getDefaultConstructor(Class<T> clazz) throws NoSuchMethodException {
Constructor<T> constructor = clazz.getDeclaredConstructor();
if ( !constructor.isAccessible() ) {
constructor.setAccessible( true );
}
return constructor;
}
static Object getProxyInstance(
Class persistentClass,
Set<Property> persistentProperties,
ExtentManager extentManager)
throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
if ( Modifier.isFinal( persistentClass.getModifiers() ) ) {
// Use the default constructor, because final classes cannot be inherited.
return useDefaultConstructor( persistentClass );
}
final ProxyConfiguration proxy = (ProxyConfiguration) Environment.getBytecodeProvider()
.getProxyFactoryFactory()
.buildBasicProxyFactory( persistentClass, new Class[] { TrackableEntity.class } )
.getProxy();
proxy.$$_hibernate_set_interceptor( new EntityProxyMethodHandler(proxy,persistentClass.getName(),
persistentProperties,
extentManager
) );
return proxy;
}
private static Object useDefaultConstructor(Class<?> clazz)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
if ( !entityConstructorMap.containsKey( clazz ) ) {
entityConstructorMap.put( clazz, getDefaultConstructor( clazz ) );
}
final Constructor<?> c = entityConstructorMap.get( clazz );
return c.newInstance();
}
}
当我 运行 一个包含访问代理字段之一的测试时,我得到一个无穷无尽的以下调用堆栈:
EntityProxyMethodHandler.intercept(EntityProxyMethodHandler.java:105)
Employee.$HibernateBasicProxy$Rbz7NDpP.getSupervisor(Unknown Source)
Caused by java.lang.reflect.InvocationTargetException:
EntityProxyMethodHandler.intercept(EntityProxyMethodHandler.java:105)
Employee.$HibernateBasicProxy$Rbz7NDpP.getSupervisor(Unknown Source)
由于某种原因,它没有调用真正的实体,而是代理本身,陷入了无限循环的拦截。我不知道如何解决这个问题,我试过在方法处理程序中找到一种调用 "target" 的方法,但找不到任何东西,因为由于某种原因,代理工厂生成的代理没有实现HibernateProxy-接口。也许这是 ByteBuddy 有一些方法可以解决的问题,但是由于我对框架没有经验,所以我还没有找到方法。
此外,在我改用 Javassist-proxies 之前,它工作得很好。然后我有类似的 类:
public class EntityProxyFactory {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger(AutofetchLazyInitializer.class);
private static final MethodFilter FINALIZE_FILTER = new MethodFilter() {
@Override
public boolean isHandled(Method m) {
// skip finalize methods
return !(m.getParameterTypes().length == 0 && m.getName().equals("finalize"));
}
};
private static final ConcurrentMap<Class<?>, Class<?>> entityFactoryMap = new ConcurrentHashMap<>();
private static final ConcurrentMap<Class<?>, Constructor<?>> entityConstructorMap = new ConcurrentHashMap<>();
//if entityFactoryMap doesnt contain that specific class, add it
private static Class<?> getProxyFactory(Class<?> persistentClass, String idMethodName) {
// Not sure how enhancer work, but it seems like you tell enhancer what type of subclasses that can be created, and all the method calls will be intercepted by entitycallbackfilter
if (!entityFactoryMap.containsKey(persistentClass)) {
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(persistentClass);
factory.setInterfaces(new Class[]{TrackableEntity.class});
factory.setFilter(FINALIZE_FILTER);
entityFactoryMap.putIfAbsent(persistentClass, factory.createClass());
}
return entityFactoryMap.get(persistentClass);
}
private static <T> Constructor<T> getDefaultConstructor(Class<T> clazz) throws NoSuchMethodException {
Constructor<T> constructor = clazz.getDeclaredConstructor();
if (!constructor.isAccessible()) {
constructor.setAccessible(true);
}
return constructor;
}
public static Object getProxyInstance(Class persistentClass, String idMethodName, Set<Property> persistentProperties,
ExtentManager extentManager)
throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
if (Modifier.isFinal(persistentClass.getModifiers())) {
// Use the default constructor, because final classes cannot be inherited.
return useDefaultConstructor(persistentClass);
}
Class<?> factory = getProxyFactory(persistentClass, idMethodName);
try {
final Object proxy = factory.newInstance();
((Proxy) proxy).setHandler(new EntityProxyMethodHandler(persistentProperties, extentManager));
return proxy;
} catch (IllegalAccessException | InstantiationException e) {
return useDefaultConstructor(persistentClass);
}
}
private static Object useDefaultConstructor(Class<?> clazz) throws NoSuchMethodException, InstantiationException,
InvocationTargetException, IllegalAccessException {
if (!entityConstructorMap.containsKey(clazz)) {
entityConstructorMap.put(clazz, getDefaultConstructor(clazz));
}
final Constructor<?> c = entityConstructorMap.get(clazz);
return c.newInstance((Object[]) null);
}
}
public class EntityProxyMethodHandler implements MethodHandler, Serializable {
private final EntityTracker entityTracker;
public EntityProxyMethodHandler(Set<Property> persistentProperties, ExtentManager extentManager) {
this.entityTracker = new EntityTracker(persistentProperties, extentManager);
}
@Override
public Object invoke(Object obj, Method thisMethod, Method proceed, Object[] args) throws Throwable {
if (args.length == 0) {
if (thisMethod.getName().equals("disableTracking")) {
boolean oldValue = entityTracker.isTracking();
entityTracker.setTracking(false);
return oldValue;
} else if (thisMethod.getName().equals("enableTracking")) {
boolean oldValue = entityTracker.isTracking();
entityTracker.setTracking(true);
return oldValue;
} else if (thisMethod.getName().equals("isAccessed")) {
return entityTracker.isAccessed();
}
} else if (args.length == 1) {
if (thisMethod.getName().equals("addTracker") && thisMethod.getParameterTypes()[0].equals(Statistics.class)) {
entityTracker.addTracker((Statistics) args[0]);
return null;
} else if (thisMethod.getName().equals("addTrackers") && thisMethod.getParameterTypes()[0].equals(Set.class)) {
@SuppressWarnings("unchecked")
Set<Statistics> newTrackers = (Set) args[0];
entityTracker.addTrackers(newTrackers);
return null;
} else if (thisMethod.getName().equals("extendProfile") && thisMethod.getParameterTypes()[0].equals(Statistics.class)) {
entityTracker.extendProfile((Statistics) args[0], obj);
return null;
} else if (thisMethod.getName().equals("removeTracker") && thisMethod.getParameterTypes()[0].equals(Statistics.class)) {
entityTracker.removeTracker((Statistics) args[0]);
return null;
}
}
entityTracker.trackAccess(obj);
return proceed.invoke(obj, args);
}
有谁知道如何在我的方法处理程序中调用真实的实体对象?
这是我 运行 单元测试时堆栈跟踪的一部分,原因是重复 "infinitely":
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.autofetch.hibernate.EntityProxyMethodHandler.intercept(EntityProxyMethodHandler.java:105)
at org.autofetch.test.Employee$HibernateBasicProxy$dbvGRz97.getSupervisor(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.autofetch.hibernate.AutofetchLazyInitializer.intercept(AutofetchLazyInitializer.java:123)
at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:95)
at org.autofetch.test.Employee$HibernateProxy$PajATc2c.getSupervisor(Unknown Source)
at org.autofetch.test.ExtentTest.secondLevelSupervisorAccess(ExtentTest.java:533)
at org.autofetch.test.ExtentTest.testSecondLevelSupervisorAccess(ExtentTest.java:246)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.hibernate.testing.junit4.ExtendedFrameworkMethod.invokeExplosively(ExtendedFrameworkMethod.java:45)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:298)
at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:292)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.autofetch.hibernate.EntityProxyMethodHandler.intercept(EntityProxyMethodHandler.java:105)
at org.autofetch.test.Employee$HibernateBasicProxy$dbvGRz97.getSupervisor(Unknown Source)
... 30 more
如果您想调用原始方法,可以使用 @SuperMethod Method m
或 @SuperCall Callable<?> c
.
获取它
使用可调用代理是开销最小的方法,这样做,您不需要获取参数数组。
我目前正在为 Hibernate 迁移一个旧工具,以根据实体统计信息自动进行预取。旧工具使用 Hibernate 3.1,因此还有一些工作要做。传统上,Hibernate 使用 CGlib 代理,但在我为最新版本的 Hibernate 开发时,我将代理生成更改为 ByteBuddy。
但是,自从更改为 ByteBuddy 后,我在让 MethodHandler 工作方面遇到了一些问题。我的工具中的方法处理程序应该处理所有对代理的调用,以收集必要的统计信息。目前,我的方法处理程序如下所示:
public class EntityProxyMethodHandler implements ProxyConfiguration.Interceptor, Serializable {
private final EntityTracker entityTracker;
private final Object proxiedObject;
private final String proxiedClassName;
EntityProxyMethodHandler(
Object proxiedObject,
String proxiedClassName,
Set<Property> persistentProperties,
ExtentManager extentManager) {
this.proxiedObject = proxiedObject;
this.proxiedClassName = proxiedClassName;
this.entityTracker = new EntityTracker(persistentProperties, extentManager );
}
@Override
@RuntimeType
public Object intercept(@This Object instance, @Origin Method method, @AllArguments Object[] arguments)
throws Exception {
final String methodName = method.getName();
if ( "toString".equals( methodName ) ) {
return proxiedClassName + "@" + System.identityHashCode( instance );
}
else if ( "equals".equals( methodName ) ) {
return proxiedObject == instance;
}
else if ( "hashCode".equals( methodName ) ) {
return System.identityHashCode( instance );
}
else if ( arguments.length == 0 ) {
switch ( methodName ) {
case "disableTracking": {
boolean oldValue = entityTracker.isTracking();
entityTracker.setTracking( false );
return oldValue;
}
case "enableTracking": {
boolean oldValue = entityTracker.isTracking();
entityTracker.setTracking( true );
return oldValue;
}
case "isAccessed":
return entityTracker.isAccessed();
default:
break;
}
}
else if ( arguments.length == 1 ) {
if ( methodName.equals( "addTracker" ) && method.getParameterTypes()[0].equals( Statistics.class ) ) {
entityTracker.addTracker( (Statistics) arguments[0] );
return null;
}
else if ( methodName.equals( "addTrackers" ) && method.getParameterTypes()[0].equals( Set.class ) ) {
@SuppressWarnings("unchecked")
Set<Statistics> newTrackers = (Set) arguments[0];
entityTracker.addTrackers( newTrackers );
return null;
}
else if ( methodName
.equals( "extendProfile" ) && method.getParameterTypes()[0].equals( Statistics.class ) ) {
entityTracker.extendProfile( (Statistics) arguments[0], instance );
return null;
}
else if ( methodName
.equals( "removeTracker" ) && method.getParameterTypes()[0].equals( Statistics.class ) ) {
entityTracker.removeTracker( (Statistics) arguments[0] );
return null;
}
}
entityTracker.trackAccess( instance );
return method.invoke( instance, arguments ); // Gets stuck here, the method interception gets intercepted endlessly
}
代理工厂看起来像这样:
public class EntityProxyFactory {
private static SessionFactoryImplementor sessionFactory = AutofetchIntegrator.getSessionFactory();
private static final ConcurrentMap<Class<?>, Constructor<?>> entityConstructorMap = new ConcurrentHashMap<>();
private static <T> Constructor<T> getDefaultConstructor(Class<T> clazz) throws NoSuchMethodException {
Constructor<T> constructor = clazz.getDeclaredConstructor();
if ( !constructor.isAccessible() ) {
constructor.setAccessible( true );
}
return constructor;
}
static Object getProxyInstance(
Class persistentClass,
Set<Property> persistentProperties,
ExtentManager extentManager)
throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
if ( Modifier.isFinal( persistentClass.getModifiers() ) ) {
// Use the default constructor, because final classes cannot be inherited.
return useDefaultConstructor( persistentClass );
}
final ProxyConfiguration proxy = (ProxyConfiguration) Environment.getBytecodeProvider()
.getProxyFactoryFactory()
.buildBasicProxyFactory( persistentClass, new Class[] { TrackableEntity.class } )
.getProxy();
proxy.$$_hibernate_set_interceptor( new EntityProxyMethodHandler(proxy,persistentClass.getName(),
persistentProperties,
extentManager
) );
return proxy;
}
private static Object useDefaultConstructor(Class<?> clazz)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
if ( !entityConstructorMap.containsKey( clazz ) ) {
entityConstructorMap.put( clazz, getDefaultConstructor( clazz ) );
}
final Constructor<?> c = entityConstructorMap.get( clazz );
return c.newInstance();
}
}
当我 运行 一个包含访问代理字段之一的测试时,我得到一个无穷无尽的以下调用堆栈:
EntityProxyMethodHandler.intercept(EntityProxyMethodHandler.java:105)
Employee.$HibernateBasicProxy$Rbz7NDpP.getSupervisor(Unknown Source)
Caused by java.lang.reflect.InvocationTargetException:
EntityProxyMethodHandler.intercept(EntityProxyMethodHandler.java:105)
Employee.$HibernateBasicProxy$Rbz7NDpP.getSupervisor(Unknown Source)
由于某种原因,它没有调用真正的实体,而是代理本身,陷入了无限循环的拦截。我不知道如何解决这个问题,我试过在方法处理程序中找到一种调用 "target" 的方法,但找不到任何东西,因为由于某种原因,代理工厂生成的代理没有实现HibernateProxy-接口。也许这是 ByteBuddy 有一些方法可以解决的问题,但是由于我对框架没有经验,所以我还没有找到方法。
此外,在我改用 Javassist-proxies 之前,它工作得很好。然后我有类似的 类:
public class EntityProxyFactory {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger(AutofetchLazyInitializer.class);
private static final MethodFilter FINALIZE_FILTER = new MethodFilter() {
@Override
public boolean isHandled(Method m) {
// skip finalize methods
return !(m.getParameterTypes().length == 0 && m.getName().equals("finalize"));
}
};
private static final ConcurrentMap<Class<?>, Class<?>> entityFactoryMap = new ConcurrentHashMap<>();
private static final ConcurrentMap<Class<?>, Constructor<?>> entityConstructorMap = new ConcurrentHashMap<>();
//if entityFactoryMap doesnt contain that specific class, add it
private static Class<?> getProxyFactory(Class<?> persistentClass, String idMethodName) {
// Not sure how enhancer work, but it seems like you tell enhancer what type of subclasses that can be created, and all the method calls will be intercepted by entitycallbackfilter
if (!entityFactoryMap.containsKey(persistentClass)) {
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(persistentClass);
factory.setInterfaces(new Class[]{TrackableEntity.class});
factory.setFilter(FINALIZE_FILTER);
entityFactoryMap.putIfAbsent(persistentClass, factory.createClass());
}
return entityFactoryMap.get(persistentClass);
}
private static <T> Constructor<T> getDefaultConstructor(Class<T> clazz) throws NoSuchMethodException {
Constructor<T> constructor = clazz.getDeclaredConstructor();
if (!constructor.isAccessible()) {
constructor.setAccessible(true);
}
return constructor;
}
public static Object getProxyInstance(Class persistentClass, String idMethodName, Set<Property> persistentProperties,
ExtentManager extentManager)
throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
if (Modifier.isFinal(persistentClass.getModifiers())) {
// Use the default constructor, because final classes cannot be inherited.
return useDefaultConstructor(persistentClass);
}
Class<?> factory = getProxyFactory(persistentClass, idMethodName);
try {
final Object proxy = factory.newInstance();
((Proxy) proxy).setHandler(new EntityProxyMethodHandler(persistentProperties, extentManager));
return proxy;
} catch (IllegalAccessException | InstantiationException e) {
return useDefaultConstructor(persistentClass);
}
}
private static Object useDefaultConstructor(Class<?> clazz) throws NoSuchMethodException, InstantiationException,
InvocationTargetException, IllegalAccessException {
if (!entityConstructorMap.containsKey(clazz)) {
entityConstructorMap.put(clazz, getDefaultConstructor(clazz));
}
final Constructor<?> c = entityConstructorMap.get(clazz);
return c.newInstance((Object[]) null);
}
}
public class EntityProxyMethodHandler implements MethodHandler, Serializable {
private final EntityTracker entityTracker;
public EntityProxyMethodHandler(Set<Property> persistentProperties, ExtentManager extentManager) {
this.entityTracker = new EntityTracker(persistentProperties, extentManager);
}
@Override
public Object invoke(Object obj, Method thisMethod, Method proceed, Object[] args) throws Throwable {
if (args.length == 0) {
if (thisMethod.getName().equals("disableTracking")) {
boolean oldValue = entityTracker.isTracking();
entityTracker.setTracking(false);
return oldValue;
} else if (thisMethod.getName().equals("enableTracking")) {
boolean oldValue = entityTracker.isTracking();
entityTracker.setTracking(true);
return oldValue;
} else if (thisMethod.getName().equals("isAccessed")) {
return entityTracker.isAccessed();
}
} else if (args.length == 1) {
if (thisMethod.getName().equals("addTracker") && thisMethod.getParameterTypes()[0].equals(Statistics.class)) {
entityTracker.addTracker((Statistics) args[0]);
return null;
} else if (thisMethod.getName().equals("addTrackers") && thisMethod.getParameterTypes()[0].equals(Set.class)) {
@SuppressWarnings("unchecked")
Set<Statistics> newTrackers = (Set) args[0];
entityTracker.addTrackers(newTrackers);
return null;
} else if (thisMethod.getName().equals("extendProfile") && thisMethod.getParameterTypes()[0].equals(Statistics.class)) {
entityTracker.extendProfile((Statistics) args[0], obj);
return null;
} else if (thisMethod.getName().equals("removeTracker") && thisMethod.getParameterTypes()[0].equals(Statistics.class)) {
entityTracker.removeTracker((Statistics) args[0]);
return null;
}
}
entityTracker.trackAccess(obj);
return proceed.invoke(obj, args);
}
有谁知道如何在我的方法处理程序中调用真实的实体对象?
这是我 运行 单元测试时堆栈跟踪的一部分,原因是重复 "infinitely":
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.autofetch.hibernate.EntityProxyMethodHandler.intercept(EntityProxyMethodHandler.java:105)
at org.autofetch.test.Employee$HibernateBasicProxy$dbvGRz97.getSupervisor(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.autofetch.hibernate.AutofetchLazyInitializer.intercept(AutofetchLazyInitializer.java:123)
at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:95)
at org.autofetch.test.Employee$HibernateProxy$PajATc2c.getSupervisor(Unknown Source)
at org.autofetch.test.ExtentTest.secondLevelSupervisorAccess(ExtentTest.java:533)
at org.autofetch.test.ExtentTest.testSecondLevelSupervisorAccess(ExtentTest.java:246)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.hibernate.testing.junit4.ExtendedFrameworkMethod.invokeExplosively(ExtendedFrameworkMethod.java:45)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:298)
at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:292)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.autofetch.hibernate.EntityProxyMethodHandler.intercept(EntityProxyMethodHandler.java:105)
at org.autofetch.test.Employee$HibernateBasicProxy$dbvGRz97.getSupervisor(Unknown Source)
... 30 more
如果您想调用原始方法,可以使用 @SuperMethod Method m
或 @SuperCall Callable<?> c
.
使用可调用代理是开销最小的方法,这样做,您不需要获取参数数组。