Java反射和代理定义和应用详解

目录

反射

1.为什么会有反射

2.什么是反射

3.java创建对象的方式:new对象、通过反射创建对象 对象的复制、反序列化

4.怎么通过反射来创建对象、获取类信息

第一步:获取class对象(三种方式分别对应三个阶段)

第二步:获取类信息(变量、方法、构造器、父类、接口等都是类信息)

 代理

1代理模式定义

2.为什么会有代理模式/代理的目的

3. 三种实现方式:JDK静态代理,JDK动态代理和CGLIB代理

        ①、JDK静态代理

        ②、JDK动态代理

        ③、CGLIB代理


反射

1.为什么会有反射

   要想运行java程序必须调用main方法,但是在学习运行servlet时没有main方法

2.什么是反射

   反射就是能够获取类信息的能力

3.java创建对象的方式:new对象、通过反射创建对象 对象的复制、反序列化

Java创建对象的四种方式_qq_52240237的博客-CSDN博客

4.怎么通过反射来创建对象、获取类信息

第一步:获取class对象(三种方式分别对应三个阶段)

第二步:获取类信息(变量、方法、构造器、父类、接口等都是类信息)

        ①、获取变量

getDeclaredFields( ):获取所有类型的变量,结果用数组呈现

getFields( ):获得public类型,结果用数组呈现

getDeclaredFiled( ):获取单个的所有类型变量,结果用变量呈现

getFiled():获取单个的public类型,结果用变量呈现

        ②、获取方法

(将变量中的Filed改为方法Method,应用方法与变量相同)

(String.class使用反射的方式代指的类对象)

        ③、构造器

(将变量中的Filed改为构造器Constructor,应用方法与变量相同)

第三步:对类信息进行操作(变量赋值取值、方法的运行、通过构造器构造对象)

        ①、反射对值的操作

(对于私有的数据需要通过暴力反射来修改)

        ②、反射对方法的操作

        ③、反造射对构器的操作 

 5.java程序在计算机中所要经历的三个阶段

(class类对象,将数据封装到数组中)

(类加载器将.class文件从磁盘加载到内存中并用数组封装,然后再加载到方法区中)

 代理

1代理模式定义

        给目标对象提供一个代理对象并且由代理对象控制对目标对象的引用

2.为什么会有代理模式/代理的目的

        ①、增强功能:通过代理业务对原有业务进行增强

        ②、控制访问:通过代理对象的方式间接的访问目标对象,防止直接访问目标对象给系统带来不必要的复杂性

3. 三种实现方式:JDK静态代理,JDK动态代理和CGLIB代理

        ①、JDK静态代理

                a、通过继承实现代理

通过继承被代理对象,重写被代理方法,可以对其进行代理。

优点:被代理类无需实现接口
缺点:只能代理这个类,要想代理其他类,要想代理其他类需要写新的代理方法。
cglib动态代理就是采用这种方式对类进行代理。不过类是由cglib帮我们在内存中动态生成的。

public class Tank{
    public void move() {
        System.out.println("Tank moving cla....");
    }

    public static void main(String[] args) {
        new ProxyTank().move();
    }
}
class ProxyTank extends Tank{
    @Override
    public void move() {
        System.out.println("方法执行前...");
        super.move();
        System.out.println("方法执行后...");
    }
}
 

                b、通过组合实现代理

        定义一个 Movable 接口被代理类需要和代理类都需要实现该接口。(接口在这里的目的就是起一个规范作用保证被代理类和代理类都实现了move()方法)。代理类需要将该接口作为属性,实例化时需要传入该接口的对象,这样该代理类就可以实现代理所有实现Movable的类了。

优点:可以代理所有实现接口的类。
缺点:被代理的类必须实现接口。

JDK动态代理就是采用的这种方式实现的。同样的代理类是由JDK自动帮我们在内存生成的。

public class Tank implements Movable{
    @Override
    public void move() {
        System.out.println("Tank moving cla....");
    }

    public static void main(String[] args) {
        Tank tank = new Tank();
        new LogProxy(tank).move();
    }
}

class LogProxy implements Movable{
    private Movable movable;
    public LogProxy(Movable movable) {
        this.movable = movable;
    }
    @Override
    public void move() {
        System.out.println("方法执行前....");
        movable.move();
        System.out.println("方法执行后....");
    }
}
interface Movable {
    void move();
}
 

        ②、JDK动态代理

通过java提供的Proxy类帮我们创建代理对象。

优点:可以生成所有实现接口的代理对象
缺点:JDK反射生成代理必须面向接口, 这是由Proxy的内部实现决定的。生成代理的方法中你必须指定实现类的接口,它根据这个接口来实现代理类生成的所实现的接口。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * 使用jdk的动态代理
 */
public class Tank implements Movable{
    @Override
    public void move() {
        System.out.println("Tank moving cla....");
    }

    public static void main(String[] args) {
        Tank tank = new Tank();
        // reflection 反射 通过二进制字节码分析类的属性和方法

        //newProxyInstance: 创建代理对象
        // 参数一: 被代理类对象
        // 参数二:接口类对象  被代理对象所实现的接口
        // 参数三:调用处理器。 被调用对象的那个方法被调用后该如何处理
        Movable o = (Movable)Proxy.newProxyInstance(Tank.class.getClassLoader()
                ,new Class[]{Movable.class}
                ,new LogProxy(tank));
        o.move();
    }
}

class LogProxy implements InvocationHandler {
    private Movable movable;

    public LogProxy(Movable movable) {
        this.movable = movable;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("方法:"+method.getName()+"()执行前");
        Object invoke = method.invoke(movable, args);  // 此处相当于 movable.move()
        System.out.println("方法:"+method.getName()+"()执行后");
        return invoke;
    }
}

interface Movable {
    void move();
}
 

        ③、CGLIB代理

CGLib(Code Generate Library) 与JDK动态代理不同的是,cglib生成代理是被代理对象的子类。因此它拥有继承方法实现静态代理的

优点:不需要被代理对象实现某个接口。
缺点:不能给final类生成代理,因为final类无法拥有子类。

<dependency>
     <groupId>cglib</groupId>
     <artifactId>cglib</artifactId>
     <version>3.2.12</version>
 </dependency>
 

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer(); // 增强者
        enhancer.setSuperclass(Tank.class); // 指定父类
        enhancer.setCallback(new TimeMethodInterceptor()); // 当被代理对象的方法调用的时候会调用 该对象的intercept
        Tank tank = (Tank)enhancer.create();  // 动态代理的生成
        tank.move();  // 生成之后会调用
    }
}

class TimeMethodInterceptor implements MethodInterceptor{
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("生成的类名"+o.getClass().getName());
        System.out.println("生成的类的父类"+o.getClass().getSuperclass().getName());
        System.out.println("方法执行前,被代理的方法"+method.getName());
        Object result = null;
        result = methodProxy.invokeSuper(o, objects);
        System.out.println("方法执行后,被代理的方法"+method.getName());
        return result;
    }
}
class Tank{
    public void move(){
        System.out.println("Tank moving clacla....");
    }
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值