如果对Class对象的原理和来龙去脉不清晰,请查看本人下面这篇文章,本文主要阐述基于Class对象应用场景
https://blog.csdn.net/u013620306/article/details/124466796
1:场景一:动态代理
1)DK提供了java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy类,这两个类相互配合,入口是Proxy,所以我们先聊它。
2)Proxy有个静态方法:getProxyClass(ClassLoader, interfaces),只要你给它传入类加载器和一组接口,它就给你返回代理Class对象
3)Proxy还有一个静态方法:newProxyInstance(ClassLoader, interfaces, InvocationHandler),返回代理对象,代理对象在调用接口函数时,通过InvocationHandler 来回掉invoke()函数,这样就有在此函数中编写增强代码,最后通过 Method.invoke(interfaceImpl, args) 来回调接口实现类函数
1.1 :代码示例
通过Proxy的 getProxyClass(ClassLoader, interfaces)来实现
// 1: ClassLoader加载字节码文件 得到 Class对象
Class animalProxy =
Proxy.getProxyClass(Animal.class.getClassLoader(),Animal.class);
// 得到有参构造器 $Proxy0(InvocationHandler h)
try {
Constructor constructor =
animalProxy.getConstructor(InvocationHandler.class);
// 2:反射获取代理实例
try {
Animal animalProxyImpl = (Animal) constructor.newInstance(new
InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 4: 回调 InvocationHandler的 invoke() 函数
Animal animalImpl = new AnimalImpl();
if (method.getName().equals("sleep")) {
System.out.println("睡觉盖被子");
try {
method.invoke(animalImpl,null);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} else if (method.getName().equals("eat")) {
System.out.println("吃肉喝酒");
try {
method.invoke(animalImpl,null);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
return null;
}
});
// 3: 代理对象 调用 Animal接口方法
animalProxyImpl.eat();
animalProxyImpl.sleep();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
AnimalImpl.java
public class AnimalImpl implements Animal{
@Override
public void eat() {
System.out.println("长高高");
}
@Override
public void sleep() {
System.out.println("身体好");
}
}
Animal.java
public interface Animal {
public void eat();
public void sleep();
}
打印:
吃肉喝酒
长高高
睡觉盖被子
身体好
通过 Proxy.newProxyInstance()函数来实现
Class<Animal> animalClass = null;
try {
animalClass = (Class<Animal>)
Class.forName("io.reactivex.rxjava3.android.samples.proxy.Animal");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Class<?>[] classes = {animalClass};
Animal animalImpl = new AnimalImpl();
Object instance = Proxy.newProxyInstance(Animal.class.getClassLoader(),classes,
new InterfaceInvocationHandler(animalImpl));
Animal animal = (Animal) instance;
animal.eat();
animal.sleep();
public class InterfaceInvocationHandler implements InvocationHandler {
private final Animal animalImpl;
public InterfaceInvocationHandler(Animal animal) {
this.animalImpl = animal;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
if (method.getName().equals("sleep")) {
System.out.println("睡觉盖被子");
try {
method.invoke(animalImpl,null);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} else if (method.getName().equals("eat")) {
System.out.println("吃肉喝酒");
try {
method.invoke(animalImpl,null);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
return null;
}
打印:
吃肉喝酒
长高高
睡觉盖被子
身体好
上面两种方法,目标都像都是要预先构造出来,那么我们能不能再次优化下,封装函数,目标函数从外部引入
public static void main(String[] args) throws Throwable {
CalculatorImpl target = new CalculatorImpl();
// 从外部传入 目标对象
Calculator calculatorProxy = (Calculator) getProxy(target);
calculatorProxy.add(1, 2);
calculatorProxy.subtract(2, 1);
}
private static Object getProxy(final Object target) throws Exception {
Object proxy = Proxy.newProxyInstance(
/*类加载器*/
target.getClass().getClassLoader(),
/*让代理对象和目标对象实现相同接口*/
target.getClass().getInterfaces(),
/*代理对象的方法最终都会被JVM导向它的invoke方法*/
new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName() + "方法开始执行...");
Object result = method.invoke(target, args);
System.out.println(result);
System.out.println(method.getName() + "方法执行结束...");
return result;
}
}
);
return proxy;
}
2 :场景二:载入数据库驱动的时候
Class.forName的一个非经常见的使用方法是在载入数据库驱动的时候
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection con=DriverManager.getConnection("jdbc:sqlserver://localhost:1433;DatabaseName==JSP","jph","jph");
3:场景三:使用AIDL与电话管理Servic进行通信
Method method =Class.forName("android.os.ServiceManager")
.getMethod("getService",String.class);
// 获取远程TELEPHONY_SERVICE的IBinder对象的代理
IBinder binder =(IBinder) method.invoke(null, new Object[] { TELEPHONY_SERVICE});
// 将IBinder对象的代理转换为ITelephony对象
ITelephonytelephony = ITelephony.Stub.asInterface(binder);
// 挂断电话
telephony.endCall();