通过反射获取当前类的接口并调用
java 9 以后对于clazz.newInstance() 过时 替换成clazz.getDeclaredConstructor().newInstance()
- 知识点
- Java Class.forName()返回一个类
Class.forName()要求JVM查找并加载指定的类,作用是执行该类的静态代码段,加载了类以后还需要进行类初始化操作之后才能正常使用此类,类初始化操作就是执行一遍类的静态语句,包括静态变量的声明还有静态代码块。
** Class.forName()的作用是要求JVM查找并加载指定的类,首先要明白,java里面任何class都要装载在虚拟机上才能运行,而静态代码是和class绑定的,class装载成功就表示执行了你的静态代码了,而且以后不会再走这段静态代码了。** - clazz.getDeclaredConstructor().newInstance()
在加载完成后,一般还要调用Class下的newInstance( )静态方法来实例化对象以便操作。
- 代码段
接口
package com.company.interfaces;
public interface ClickAction {
void onClickAction();
}
实现类
package com.company;
import com.company.interfaces.ClickAction;
public class Action implements ClickAction {
@Override
public void onClickAction() {
System.out.println("Action->Click");
}
}
代理类具体实现方法
import com.company.interfaces.ClickAction;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
private ClickAction clickAction;
public MyInvocationHandler(ClickAction listener) {
this.clickAction = listener;
}
// invoke三个参数:
// proxy:就是代理对象,newProxyInstance方法的返回对象
// method:调用的方法
// args: 方法中的参数
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = method.invoke(clickAction, args);//拦截对象
System.out.println("invoke=====");
return invoke;
}
}
调用
package com.company;
import com.company.interfaces.ClickAction;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
try {
//通过反射获取到加载类
Class<?> clazz = Class.forName("com.company.Action");
//实例化加载类
Action action = (Action) clazz.getDeclaredConstructor().newInstance();
//获取加载类中的接口
Class<?> interfaces[] = clazz.getInterfaces();
通过动态代理对接口行为进行处理
//执行接口方式一
ClickAction clickAction = (ClickAction) Proxy.newProxyInstance(action.getClass().getClassLoader(), interfaces, new MyInvocationHandler(action));
clickAction.onClickAction();
//执行接口方式二
Method method = action.getClass().getDeclaredMethod("mainMethod", ClickAction.class);
method.invoke(action, clickAction);
//也可以对接口进行绑定eg btn.setOnclick(clickAction);
clickAction.onClickAction();
//也可以对接口进行绑定eg btn.setOnclick(clickAction);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
newProxyInstance,方法有三个参数:
loader: 用哪个类加载器去加载代理对象
interfaces:动态代理类需要实现的接口
h:动态代理方法在执行时,会调用h里面的invoke方法去执行
- 如果使用的接口在类内部 调用可用Class<?> clazz = Class.forName(“com.company.Action$ClickAction”);