我的目标是在调用类的getter方法的同时为该类创建一个实例,然后为新实例字段设置一个值。 (在这种情况下,如代码所示,该类是一个String,但也可以是另一个类“ Like Person类”)
...实体注释:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface Entity {
String visibileName();
}
...实现IEventDesignDialog
public class EventDesignDialog implements IEventDesignDialog{
private String show;
private String dateAndTimeDisplayFormat;
private String eventType;
@Entity(visibileName = "Show")
public String getShow() {
return this.show;
}
@Entity(visibileName = "Date And Time display format")
public String getDateAndTimeDisplayFormat() {
return this.dateAndTimeDisplayFormat;
}
@Entity(visibileName = "Event Type")
public String getEventType() {
System.out.println("get event type method invokde successfully");
return this.eventType;
}
}
IEventDesignDialog
界面:
public interface IEventDesignDialog extends IPage{
public String getShow();
public String getDateAndTimeDisplayFormat();
public String getEventType();
}
IPage
界面:
public interface IPage {
}
动态代理实现:
public class IPageProxy implements InvocationHandler {
private List<Method> entityMethods;
private Class <? extends IPage> screenClazz;
public IPageProxy(final Class <? extends IPage> screenClazz) {
entityMethods = new ArrayList<>();
getEntityAnnotatedMethods(screenClazz);
// Accept the real implementation to be proxied
this.screenClazz = screenClazz;
}
/**
* create an page instance
* @param type
* @param
* @return
* @throws InstantiationException
* @throws IllegalAccessException
*/
public static IPage getInstance(final Class<? extends IPage> type)
throws InstantiationException, IllegalAccessException {
List<Class<?>> interfaces = new ArrayList<>();
interfaces.addAll(Arrays.asList(type.getInterfaces()));
return (IPage) Proxy.newProxyInstance(
type.getClassLoader(),
findInterfaces(type),
new IPageProxy(type)
);
/*return (IPage) Proxy.newProxyInstance(type.getClassLoader(),
interfaces.toArray(new Class<?>[interfaces.size()])
, new IPageProxy(type));*/
}
/**
* get all methods that annotated with @Entity annotation
* and add it for entityMethods array List
* @param screenClazz
*/
private void getEntityAnnotatedMethods(final Class <? extends IPage> screenClazz) {
// Scan each interface method for the specific annotation
// and save each compatible method
for (final Method m : screenClazz.getDeclaredMethods()) {
if (m.isAnnotationPresent(Entity.class)) {
entityMethods.add(m);
}
}
}
static Class<?>[] findInterfaces(final Class<? extends IPage> type) {
Class<?> current = type;
do {
final Class<?>[] interfaces = current.getInterfaces();
if (interfaces.length != 0) {
return interfaces;
}
} while ((current = current.getSuperclass()) != Object.class);
throw new UnsupportedOperationException("The type does not implement any interface");
}
@Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws InvocationTargetException,
IllegalAccessException, IllegalArgumentException, InstantiationException, ParserConfigurationException, XPathExpressionException, NoSuchFieldException, SecurityException {
Method methodToInvoke = null;
for (Method methodFromClass : screenClazz.getMethods()) {
if (methodFromClass.getName().equals(method.getName())) {
methodToInvoke = methodFromClass;
break;
}
}
String fieldName = method.getName().replaceAll("get", "");
fieldName = Character.toLowerCase(fieldName.charAt(0)) + fieldName.substring(1, fieldName.length());
Field getterMethodField = methodToInvoke.getDeclaringClass().getDeclaredField(fieldName);
getterMethodField.setAccessible(true);
Class<?> returnedType = method.getReturnType();
try {
*getterMethodField.set(getterMethodField.getType().newInstance(), "");*
}catch (Exception e) {
e.printStackTrace();
}
return methodToInvoke.invoke(screenClazz.newInstance(), args);
}
主类:
public class Main {
public static void main(String[] args) {
try {
((EventDesignDialog)getInstance(EventDesignDialog.class)).getEventType();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
public static <T extends IPage> T getInstance(final Class<? extends IPage> type) throws InstantiationException, IllegalAccessException {
return (T) IPageProxy.getInstance(type);
}
}
invoke方法中的这一行代码将引发以下异常: getterMethodField.set(getterMethodField.getType()。newInstance(),“”);
java.lang.IllegalArgumentException: Can not set java.lang.String field abc.EventDesignDialog.eventType to java.lang.String
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:75)
at java.lang.reflect.Field.set(Field.java:764)
at abc.IPageProxy.invoke(IPageProxy.java:173)
at com.sun.proxy.$Proxy2.getEventType(Unknown Source)
at abc.Main.main(Main.java:9)
答案 0 :(得分:1)
methodToInvoke.getDeclaringClass()
返回Class<? extends IPage>
。
虽然
getterMethodField.getType()
返回String
。
因此,您正在尝试在eventType
类中设置java.lang.String
字段的值。
不太正确;)
getterMethodField.set(getterMethodField.getType().newInstance(), "")
^---------------^ ^---------------------------------------^
field of new instance of java.lang.String
Class<? extends IPage> Here you need an instance of ? extends IPage
您需要的是
getterMethodField.getDeclaringClass().newInstance()
无论如何,我不知道这有什么意义,因为新创建的实例会立即“丢失”。
也许您想这样做?
try {
final Object instance = getterMethodField.getDeclaringClass().newInstance();
getterMethodField.set(instance, "");
} catch (final Exception e) {
e.printStackTrace();
}
return methodToInvoke.invoke(instance, args);
}