动态代理

大家都知道,Spring中的两大核心机制之一AOP,它的原理就是java的动态代理机制,所以今天对动态代理机制进行了了解,并总结如下。

在java的动态代理机制中,有两个重要的类和接口,一个是InvocationHandler(Interface)、另一个则是Proxy(Class),这一个类和接口是我们实现动态代理所必须用到的

每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke方法来进行调用。

所以我们来看看InvocationHandler这个接口的唯一方法invoke

方法的三个参数分别代表什么:

proxy:指代我们所代理的那个真实对象

method:指代我们所要调用的真实对象的某个方法的method对象

args:指代的是调用真实对象某个方法时接收的参数

 

接下来我们再看看Proxy这个类。Proxy这个类的作用就是用来动态创建一个代理对象类,它提供了许多方法,但我们用的最多的是newProxyInstance这个方法

方法的三个参数分别代表为:

loader:一个ClassLoader对象,定义了由哪个ClassLoader对象对生成的代理对象进行加载

interface:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么借口,如果我提供了一组借口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了。

h:一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

 

介绍完基本概念后我们来看个实例吧

首先我们定义一个学生接口(Student),里面有登陆和提交两个方法

package com.javaweb.dynamicProxy;

public interface Student {
    public void login();

    public void submit();
}

接着,定义一个StudentImpl类来实现这个接口

package com.javaweb.dynamicProxy;

public class StudentImpl implements Student{
    public void login() {
        System.out.println("登录");
    }

    public void submit() {
        System.out.println("提交");
    }
}

下一步,我们就要定义一个动态代理类,前面说了,每个动态代理类都必须要实现InvocationHandler这个接口

package com.javaweb.dynamicProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {
    private Object target;  //接收传进来的被代理对象(也就是我们要代理的真实对象)

    public MyInvocationHandler(Object target){
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  //proxy是被代理对象;method是通过反射获取的method;args是方法参数
        // 在代理真实对象之前,我们可以添加一些自己的操作
        System.out.println("权限校验");

        //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
        method.invoke(target,args);    //执行被代理target对象的方法

        //在代理真实对象后我们也可以添加一些自己的操作
        System.out.println("日志记录");
        return null;
    }
}

最后,我们来看看Client类

package com.javaweb.dynamicProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Test {

    public static void main(String[] args) {
        //我们要代理的真实对象
        Student student = new StudentImpl();
        //我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的
        InvocationHandler m = new MyInvocationHandler(student);
        /*
         * 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数
         * 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象
         * 第二个参数realSubject.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了
         * 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
         */
        Student s = (Student) Proxy.newProxyInstance(student.getClass().getClassLoader(),student.getClass().getInterfaces(),m);  //通过对象反向拿到字节码文件再获取类的类加载器
        s.login();
        s.submit();
        System.out.println(s.getClass().getName());

        System.out.println("-----------------------------------------------------------");

        student.login();
        student.submit();

    }
}

最后得到的结果是

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值