1.概念
对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法。
2.主要功能:
- 在运行时判断任意一个对象所属的类;
- 在运行时构造任意一个类的对象;
- 在运行时判断任意一个类所具有的成员变量和方法;
- 在运行时调用任意一个对象的方法;
- 生成动态代理。
3.主要方法
1)获取类对象
- 通过实例对象获取类对象
Reflex reflex1 = new Reflex();
Class<? extends Reflex> aClass = reflex1.getClass();
- 通过类名.class获取类对象
Class<Reflex> reflexClass = Reflex.class;
- 通过Class.forName(“全类名”)获取类对象
Class<?> reflex = Class.forName("hash.Reflex");
if (aClass==reflexClass && aClass==reflex) {
System.out.println("类对象是唯一的");
}
2)类的方法
- 获取类中方法(不包括父类方法)
Method[] declaredMethods = reflexClass.getDeclaredMethods();
- 获取类中方法(包含父类的public方法)
Method[] methods = reflexClass.getMethods();
- 获取指定方法,传入方法名和参数类型
Method method = reflexClass.getDeclaredMethod("testMethod", int.class);
- 设置方法为可访问(忽略修饰符的影响)
method.setAccessible(true);
- 通过method方法和对象实例调用方法
Integer invoke = (Integer) method.invoke(reflex1,1);
- 获取方法名
String name = method.getName();
- 获取方法返回值类型
Class<?> returnType = method.getReturnType();
- 获取方法参数类型
Class<?>[] parameterTypes = method.getParameterTypes();
- 获取方法访问修饰符
int modifiers = method.getModifiers();
- 方法是否包含Bean注解
boolean annotationPresent = method.isAnnotationPresent(Bean.class);
- 获取Bean注解的名字
Bean bean = method.getAnnotation(Bean.class);
3)类的属性
- 获取类中的属性(不包括父类方法)
Field[] declaredFields = reflexClass.getDeclaredFields();
- 获取类中的属性(包含父类的public方法)
Field[] fields = reflexClass.getFields();
- 获取指定属性名的属性
Field field = reflexClass.getDeclaredField("name");
- 设置属性为可访问
field.setAccessible(true);
- 获取属性的值
Object o = field.get(reflex1);
- 修改属性的值
field.set(reflex1,"tcc1");
- 属性是否包含Bean注解
boolean annotationPresent = field.isAnnotationPresent(Autowired.class);
主要方法的demo测试:
public class Reflex {
private Integer age;
public String name;
public Reflex() {
}
public Reflex(Integer age, String name) {
this.age = age;
this.name = name;
}
public int testMethod(int a){
return a;
}
public static void main(String[] args) {
//方法一:通过实例对象获取类对象
Reflex reflex1 = new Reflex(1,"tcc");
Class<? extends Reflex> aClass = reflex1.getClass();
//方法二:通过类名.class获取类对象
Class<Reflex> reflexClass = Reflex.class;
//方法三:通过Class.forName("全类名")获取类对象
try {
Class<?> reflex = Class.forName("hash.Reflex");
if (aClass==reflexClass && aClass==reflex) {
System.out.println("类对象是唯一的");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//获取类中方法(不包括父类方法)
Method[] declaredMethods = reflexClass.getDeclaredMethods();
//获取类中方法(包含父类的public方法)
Method[] methods = reflexClass.getMethods();
try {
Method method = reflexClass.getDeclaredMethod("testMethod", int.class);
method.setAccessible(true);
//通过method方法和对象实例调用方法
Integer invoke = (Integer) method.invoke(reflex1,1);
System.out.println(invoke);
//获取方法名
String name = method.getName();
//获取方法返回值类型
Class<?> returnType = method.getReturnType();
//获取方法参数类型
Class<?>[] parameterTypes = method.getParameterTypes();
//获取方法访问修饰符
int modifiers = method.getModifiers();
//方法是否包含Bean注解
boolean annotationPresent = method.isAnnotationPresent(Bean.class);
//获取Bean注解的名字
Bean bean = method.getAnnotation(Bean.class);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
//获取类中的属性
Field[] declaredFields = reflexClass.getDeclaredFields();
Field[] fields = reflexClass.getFields();
try {
Field field = reflexClass.getDeclaredField("name");
//设置属性为可访问
field.setAccessible(true);
//获取属性的值
Object o = field.get(reflex1);
//修改属性的值
field.set(reflex1,"tcc1");
//属性是否包含Bean注解
// boolean annotationPresent = field.isAnnotationPresent(Autowired.class);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
4.基于反射实现的动态代理
Java标准库提供了一种动态代理(Dynamic Proxy)的机制:可以在运行期动态创建某个interface的实例,即动态代理。java动态代理机制中有两个重要的类和接口InvocationHandler(接口)和Proxy(类)。
- InvocationHandler接口是proxy代理实例的调用处理程序实现的一个接口,每一个proxy代理实例都有一个关联的调用处理程序;在代理实例调用方法时,方法调用被编码分派到调用处理程序的invoke方法,每一个动态代理类的调用处理程序都必须实现InvocationHandler接口,并且每个代理类的实例都关联到了实现该接口的动态代理类调用处理程序中,当我们通过动态代理对象调用一个方法时候,这个方法的调用就会被转发到实现InvocationHandler接口类的invoke方法来调用。
- Proxy类就是用来创建一个代理对象的类,常常使用newProxyInstance方法创建代理类对象。这个方法的作用就是创建一个代理类对象,它接收三个参数,我们来看下几个参数的含义:
- loader:一个classloader对象,定义了由哪个classloader对象对生成的代理类进行加载
- interfaces:一个interface对象数组,表示我们将要给我们的代理对象提供一组什么样的接口,如果我们提供了这样一个接口对象数组,那么也就是声明了代理类实现了这些接口,代理类就可以调用接口中声明的所有方法。
- h:一个InvocationHandler对象,表示的是当动态代理对象调用方法的时候会关联到哪一个InvocationHandler对象上,并最终由其调用。
动态代理demo测试:
public interface Hello {
public String hello();
}
public class HelloWorld implements Hello {
@Override
public String hello() {
System.out.println("执行代理对象的方法");
return "返回代理对象的结果";
}
}
public class WorkHandler implements InvocationHandler {
//被代理的对象
private Object object;
//代理类的构造函数,用于构造被代理类实例
public WorkHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用方法之前要干什么------");
Object invoke = method.invoke(object, args);
System.out.println("调用方法之后要干什么------");
return invoke;
}
public static void main(String[] args) {
//被代理的对象
Hello people = new HelloWorld();
//代理对象的调用处理程序,我们将要代理的真实对象传入代理对象的调用处理的构造函数中,代理对象的调用处理程序会调用被代理对象的方法
InvocationHandler handler = new WorkHandler(people);
Hello proxy = (Hello)Proxy.newProxyInstance(
handler.getClass().getClassLoader(),// 传入ClassLoader
people.getClass().getInterfaces(),// 传入要实现的接口
handler);//传入处理调用方法的InvocationHandler
System.out.println(proxy.hello());
}
}