JAVA反射
Class类
//使用java.exe将.class文件加载到虚拟机中,这个过程被称为类加载,而这个运行类就是Class的一个实例,换句话话说Class就是指的是运行中的类
获取Class对象的四种方式(用这四种方法得到 运行类的对象都是同一个,所以说时单例的)
Class.forname(String classname)//使用全类名构建字节码对象
类名.class
对象.getClass()
类加载器.load(String className)
Class类的常用方法
getClassLoader()//返回类加载器 ClassLoader
成员方法
newInstance()//创建该字节码原本类的实例
getFileds()//获取该类的公共属性,继承的也算
getFied(String name)//根据属性名获取公共的属性
getDeclaredFiled(String name)//根据属性名获取属性值(任意权限)
getDeclaredFields()//获取当前类的任何访问权限的属性,不包括父类的
getMethods()//获取该类的公共方法,继承的也算
getDeclaredMethods()//获取当前类的任何访问权限的方法,不包括父类的
getConstructors()//获取所有公共权限的构造器 不包括父类 因为拿父类的构造器没有用
getConstuructor(运行时类对象.....)//获取指定形参列表的构造器对象
getDeclaredConstrcutors()//获取该运行时类所有权限的狗构造器 因为拿父类的构造器没有用
getSuperClass()//获取该运行时类的父类
getGenricSuperClass()//获取带有泛型的父类
getInterFaces()//获取运行时类的接口
getPackege()//获取所在包
getDaclared(String 方法名,形参的class对象.....)
Filed类的常用方法 //反射中代表运行时类的属性
成员方法
getModifiers()//获取属性的访问权限修饰符是个常量 Modifiers.PUBLIC
getType()//获取属性类型
getName()//获取变量名
set(对象,值)//设置对象对应的属性值
setAccessible(True)//设置修改权限不够的属性允许访问,不然调用set方法会发生异常
get(对象)//指定对象调用该属性
Method类的常用方法
成员方法
getAnotations()//返回 Annotation[]对象 获取方法上的所有注解对象
getReturnType()//获取方法的返回值类型
getName()//获取方法名
getParamterTypes()//获取参数的类型
getExceptionTypes();//获取方法抛出的异
setAcessible(boolean b)//设置访问权限为可访问
invoke(对象,参数列表...)//使用对象调用该方法 该返回值就是这个方法对应的返回值 如果时静态方法对象形参这里可以写null,或者时运行时类的反射对象(更好理解)
Consturtor类的使用 //不常用 常用的时Class里面的newInstance()方法
setAccessible(true)//设置权限不够的构造器对象可以去访问
newInstance(参数…)//给定指定的实参去创建对象
ClassLoader的常用方法
这个代表类加载器
getResourceAsStream(String name)//在所在模块的的src目录下配置资源流
代理模式与动态代理
代理模式的本质就是为了增强原有类的方法
静态代理:
在编译阶段,让代理类和被代理类实现同一个接口,在被代理类中设置一个被代理的成员,然后利用构造器或者是方法的方式来初始化,实例化被代理类的时候,将需要被代理的对象传入代理类。然后调用需要被代理类的同名方法(使用多态性,将同名方法统一声明在接口中,代理类也是这个接口的子类),在被调用的代理类的内部使用那个被代理的成员去调用这个同名方法,可以在它的前面或者后面写增强的内容
缺点:每有不同接口的类需要被代理的时候都要书写一个新的代理类。所以我们使用动态代理来解决这个问题
动态代理:
使用反射技术,我们只需要让被代理的类实现接口,然后利用这个接口反射的去构建代理类就可以了
,代理类可以使用多态性用接口去接收代理类变量,然后调用需要被增强的方法即可。
package com.raoqi.testrflect;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author rqq
* @create 2022/6/22
*
* 测试动态代理
*/
public class Test2 {
public static void main(String[] args) {
//创建一个老板对象
Boss boss = new Boss();
//获取老板类的反射对象
Class<Boss> bossClass = (Class<Boss>) boss.getClass();
/**
* 创建动态代理对象
*因为要动态的代理老板,需要就要调用老板对象里面的
* 方法,所以我们需要老板类的反射对象,这样才能动态的调用老板的方法
* 在代理模式中被代理类和代理类都要实现同一个接口,所以第二参数为老板
* 反射对象的对象
*/
Action a = (Action)Proxy.newProxyInstance(bossClass.getClassLoader(), bossClass.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始代理");
//我们调用代理类对象的方法时候,他就会来调用这个方法,以我们要在这个方法的内部调用被代理类对象的方法
/**
* method代表每次调用代理对象的方法,的那个方法的反射对象
*/
method.invoke(boss, args);
System.out.println("代理结束");
return null;
}
});
a.dgs();
a.eat();
}
}
/**
* 行为接口
* 利用多态性来接收代理对象保存接口
*/
interface Action{
//打官司
void dgs();
//吃饭
void eat();
}
class Boss implements Action{
@Override
public void dgs(){
System.out.println("打官司...");
}
@Override
public void eat() {
System.out.println("吃饭...");
}
}