1.反射介绍
- 在运行阶段,动态获取类的信息和调用类的属性和方法的机制称为反射机制
2.反射的作用
- 获取对象所属的类(父类,接口)
- 通过类创建对象
- 获取对象所有的属性和方法(调用)
- 创建代理对象
3.反射采用api(java.lang.reflect)
- Class:包含类中所有的信息
- 通过类加载器在加载过程中为每一个类创建唯一的class对象。
- Class创建的三种方式
//1.类名.class
Class clz = Apple.class;
//2.对象.getClass()
Class clz2 = apple.getClass();
//3.类的全限定名称(全路径)
try {
Class clz3 = Class.forName("test.Apple");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
- 创建对象方式
/**
* 1.调用无参构造(若没有无参构造,或无参构造没有访问权限则创建失败)
* 2.接口,抽象类,数组,基本类型创建失败
*/
Apple apple = (Apple) clz.newInstance();
apple.eat();
- Field: 封装了属性对象
//获取属性
//获取封装指定public属性的field对象
Field field = clz.getField("weight");
//System.out.println(field);
//给属性赋值 apple.setWeight(12);
//对象 值
Apple apple = clz.newInstance();
field.set(apple, 12);
//获取属性的值
System.out.println(field.get(apple));
//获取所有的public修饰的属性(获取父类的属性)
/*Field [] fields = clz.getFields();
System.out.println(Arrays.toString(fields));*/
//获取所有的属性(包含私有的,不能获取父类)
Field [] fields = clz.getDeclaredFields();
System.out.println(Arrays.toString(fields));
//获取指定属性(私有的)
Field f = clz.getDeclaredField("size");
f.setAccessible(true);
f.set(apple, 11);
System.out.println(f.get(apple));
- Method: 封装方法的对象
//1.获取public修饰的指定方法
//Method method = clz.getMethod("show2");
Method method2 = clz.getMethod("show", String.class);
//执行方法的调用
method2.invoke(apple, "aaaa");
//2.获取所有的public方法(父类的)
//clz.getMethods();
//3.获取所有的方法(私有)
//clz.getDeclaredMethods();
//4.获取指定私有方法
Method method = clz.getDeclaredMethod("show2");
method.setAccessible(true);
method.invoke(apple);
- Constructor: 包含了构造方法的信息(class获取)
GetConstructor(Class…paramerType):获取公共的构造方法
GetConstructors():获取公共的所有的构造方法
getDeclaredConstructor(Class…paramerType):该类所有构造方法之一(包含私有的)
getDeclaredConstructors():获取所有的构造方法
//2.获取有参构造
//获取带有一个String类型参数的构造方法
Constructor<Apple> constructor = clz.getConstructor(String.class);
//通过constructor创建对象
Apple apple = constructor.newInstance("红色");
//apple.show();
/*Constructor<Apple> constructor = clz.getConstructor();//无参构造
Apple apple = constructor.newInstance();
System.out.println(apple);*/
//获取所有的public构造方法
/*Constructor[] constructors = clz.getConstructors();
System.out.println(Arrays.toString(constructors));*/
//获取所有的构造方法(包含私有的)
/*Constructor<?>[] declaredConstructors = clz.getDeclaredConstructors();
System.out.println(Arrays.toString(declaredConstructors));*/
//获取指定构造方法
Constructor<Apple> constructor2 = clz.getDeclaredConstructor(int.class);
//授权
constructor2.setAccessible(true);
Apple apple2 = constructor2.newInstance(1);
apple2.show();
- 反射的优点和缺点
- 优点: 灵活性和扩展性,降低了耦合性
- 缺点: 维护难度大
- 代理模式
- 开闭原则: 面向修改关闭,面向扩展开放。
- 代理模式: java语言23种设计模式。(GOF的<<设计模式>>)
- 设计模式: 经验,代码的扩展,松耦合。
- 访问对象另一种方式。给需要操作的真实对象创建代理对象,通过操作代理对象实现对真实对象的使用,可以实现对真实对象内容扩展。
- 静态代理: 在编译期间,为每一个真实对象的类创建代理类
- 每一个真实对象的方法都要添加增强。
interface Yulequan{
void play();
void kongfu();
}
class LiYiFeng implements Yulequan{
@Override
public void play() {
System.out.println("我不会play");
}
@Override
public void kongfu() {
System.out.println("我不会kongfu");
}
}
//真实对象类
class BaoQiang implements Yulequan{
@Override
public void play() {
System.out.println("我会play");
}
@Override
public void kongfu() {
System.out.println("我会kongfu");
}
}
//代理类
class SongZhe implements Yulequan{
Yulequan bq;
public SongZhe(Yulequan bq) {
this.bq = bq;
}
@Override
public void play() {
System.out.println("开始");
bq.play();
System.out.println("结束");
}
@Override
public void kongfu() {
System.out.println("开始");
bq.kongfu();
System.out.println("结束");
}
}
public class StaticProxy {
public static void main(String[] args) {
Yulequan yl = new SongZhe(new LiYiFeng());
yl.kongfu();
}
}
- 动态代理:运行期间,为真实对象创建代理对象的方式。(反射)
- JDK的动态代理(接口+真正对象的类)
//1.创建目标类对象
YuLeQuan yl = new BQ();
//2.给目标对象创建代理对象
//2.1 目标类对象实现同一个接口
//2.2 代理类对象中需要获取每一个方法
/*参数: 1.类加载器(用于加载获取class对象)
* 2.interfaces:获取目标对象所有实现的接口(获取所有方法)
* 3.invocationhandler:真正遍历处理每一个需要增强方法地方
* invoke方法: 访问一次interface的方法,该方法就调用一次
* */
YuLeQuan proxy = (YuLeQuan) Proxy.newProxyInstance(
yl.getClass().getClassLoader(),
yl.getClass().getInterfaces(),
new InvocationHandler() {
//proxy:代理
//method:封装了每一个遍历的方法
//args:方法参数
//object 返回值
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始");
//调用方法并返回
Object obj = method.invoke(yl, args);
System.out.println("结束");
return obj;
}
});
//3.调用代理对象方法
proxy.play();
proxy.kongfu();
- Cglib的动态代理(目标类)
- 导入jar(cglib.jar,asm.jar)
//1.创建目标类对象
Lyf lyf = new Lyf();
//2.创建代理对象
Enhancer enhancer = new Enhancer();
//2.1 说明父子关系
enhancer.setSuperclass(Lyf.class);
//2.2 方法怎么处理(回调机制) 拦截每一个方法然后添加增强
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("开始");
Object obj = method.invoke(lyf, args);
System.out.println("结束");
return obj;
}
});
Lyf ly = (Lyf) enhancer.create();
//3.调用方法
ly.play();