JAVA反射和动态代理
1. 反射
1. 反射机制的定义:
反射是在运行状态中,对于任意的一个类,都能够知道这个类的所有属性和方法,对任意一个对象都能够通过反射机制调用一个类的任意方法,这种动态获取类信息及动态调用类对象方法的功能称为java的反射机制。
2. 反射的作用:
1、动态地创建类的实例,将类绑定到现有的对象中,或从现有的对象中获取类型。
2、应用程序需要在运行时从某个特定的程序集中载入一个特定的类
3.应用
- 获取其Class对象的时候不,类不会被加载,当通过Class.forName()获取其类对象引用的时候类会被加载
public class Main {
public static void main(String[] args) {
// 不会初始化静态块
Class clazz1 = String.class;
System.out.println("------");
// 会初始化
Class clazz2 = Class.forName("java.lang.String");
}
}
2.动态代理——JDK动态代理
JDK动态代理只提供接口的代理,不支持类的代理
代码示例
public interface Project {
String sayHello(String name);
void sayBay();
}
public class RealProject implements Project{
public String sayHello(String name) {
System.out.println("你好"+name);
return "你好"+name;
}
public void sayBay() {
System.out.println("ByeBye");
}
}
public class InvocationHandlerImpl implements InvocationHandler {
private Project project;
public InvocationHandlerImpl(Project project) {
this.project = project;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我在调用之前...");
//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
Object returnValue = method.invoke(project, args);
//在代理真实对象后我们也可以添加一些自己的操作
System.out.println("我在调用之后...");
return returnValue;
}
}
public class Test {
public static void main(String[] args) throws Throwable {
//代理的真实对象
Project realSubject = new RealProject();
//传入了真实的对象,代理方法会调用真实对象的方法
InvocationHandler handler = new InvocationHandlerImpl(realSubject);
//该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
ClassLoader loader = realSubject.getClass().getClassLoader();
Class[] interfaces = realSubject.getClass().getInterfaces();
Project project = (Project) Proxy.newProxyInstance(loader, interfaces, handler);
System.out.println("动态代理对象:"+project.getClass().getName());
project.sayBay();
System.out.println("-----------------------------------");
Object[] args2 = new Object[1];
args2[0] = "zlz";
handler.invoke(realSubject, Project.class.getMethod("sayHello", String.class), args2);
}
}
运行结果:
动态代理对象:com.sun.proxy.$Proxy0
我在调用之前...
ByeBye
我在调用之后...
-----------------------------------
我在调用之前...
你好zlz
我在调用之后...
第一种方法通过 Proxy.newProxyInstance()方法创建代理对象。
代理对象的类型是com.sun.proxy.$Proxy0 指向了 Project 类型的引用project。
执行project.sayBay()方法时。最终还是像第二个方法一样,调用代理处理器实现类的invoke()方法,实现动态代理,执行三部曲:
- 前置方法输出我在调用之前…
- 调用被代理对象的sayHello()方法
- 后置方法输出我在调用之后…