java 动态代理实现

原创 2016年05月31日 12:00:09

最近在写Java服务器,一边学一边做,所以很多基础的不是很清楚,遇到了拦截器都说本质是动态代理。所以好好的看了下。
java的代理用我的理解就是:为了在接口的方法执行之前或之后添加一些相关操作所以绕个圈用反射获取方法再执行,这么做更多的是考虑代码的可拓展性和解耦合。
jdk的动态代理是基于实现接口完成的,所以我们首先要定义接口,这里我们定义两个接口:

public interface DrinkService {
    /**
     * 普通的接口,用于代理
     * */
 public String drinkFood(String food);
}

public interface EatService {
    /**
     * 接口用于动态代理测试
     * */
    public String eatFood(String food);
}

这个两个接口中分别有一个方法,然后要有一个类来实现这些接口,在实际的业务中这个类创建的对象就是用来处理实际业务的,也是被代理对象。我们会采用反射来在代理中调用这个对象的方法,注意这个方法是实现自接口的方法。

/**
 * 被代理的类,jdk的动态代理只能代理接口
 * */
public class DrinkAndEat implements EatService,DrinkService{
    /**
     * 实现接口EatService
     * */
    @Override
    public String eatFood(String food) {
        System.out.println("吃"+food);
        return "吃"+food;
    }
    /**
     * 实现接口DrinkService
     * */
    @Override
    public String drinkFood(String food) {
        System.out.println("喝"+food);
        return "喝"+food;
    }
}

好了到了这里我的前置准备已经完成了,正常的业务也都是这么做的,现在我们需要给这个类设置也给动态代理,所以我们要定义一个类,这个类实现InvocationHandler接口,并且和要被代理的类绑定,如果绑定很简单:在这个类中写个属性,属性类型就是这个类。
在这个类中要实现接口的方法:

 public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable

在这个方法中我们会通过反射机制调用被代理类的方法,同样的java 服务器中的拦截也是在这个方法中实现的,看具体代码:

/**
 * 触发器,动态代理是通过这个触发器调用具体的业务实现方法的
 * */
public class InvocationHandlerImpl implements InvocationHandler{
    /**
     * 被代理的对象,即实现具体业务的对象
     * */
    private DrinkAndEat de;

    public void setDe(DrinkAndEat de) {
        this.de = de;
    }

    /**
     * 代理通过这个方法调用具体的业务实现
     * */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
        //可在此进行方法调用之前的拦截
        System.out.println("方法执行之前拦截");
        Object test = method.invoke(de,args[0]);
        System.out.println("方法执行之后拦截");
        return test;
    }

}

要注意的是:Object test = method.invoke(de,args[0]);
中invoke方法的返回值,就是被代理类中方法的返回值,在Object invoke(Object proxy, Method method, Object[] args) throws Throwable这个方法中我们要将前面的返回值test返回,只有这样我们才可以在外面代理中获取被代理类的方法的返回值的。
下面我们就进行测试:
首先我们要创建代理:

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

在这个方法中我们需要三个参数,一个是被代理类的加载器这样获取:

DrinkAndEat de = new DrinkAndEat();
        ClassLoader loader = de.getClass().getClassLoader();

一个是被代理类中的接口方法:

Class[] interfaces = de.getClass().getInterfaces();

最后一个参数就是我们刚刚创建的实现了InvocationHandler接口的类:

InvocationHandlerImpl handler = new InvocationHandlerImpl();
        handler.setDe(de);

然后我们创建代理:

Object test = Proxy.newProxyInstance(loader, interfaces, handler);

代理创建出来后要进行类型转换,我们将这个代理类型强转成接口类型,再调用方法:

DrinkService drink = (DrinkService) test;
        EatService eat = (EatService)test;
        String drinkString = drink.drinkFood("水");
        String eatString = eat.eatFood("米饭");

这是测试的完整代码:

DrinkAndEat de = new DrinkAndEat();
        ClassLoader loader = de.getClass().getClassLoader();
        Class[] interfaces = de.getClass().getInterfaces();
        InvocationHandlerImpl handler = new InvocationHandlerImpl();
        handler.setDe(de);
        Object test = Proxy.newProxyInstance(loader, interfaces, handler);
        DrinkService drink = (DrinkService) test;
        EatService eat = (EatService)test;
        String drinkString = drink.drinkFood("水");
        String eatString = eat.eatFood("米饭");
版权声明:本文已经搬迁到博主个人网站:http://13fafa.cn。

JAVA动态代理用法与实现过程

jdk动态代理实现已即原理
  • qq1004642027
  • qq1004642027
  • 2016年08月02日 11:33
  • 1981

Java动态代理的两种实现方法

1、定义接口和实现 package com.meituan.hyt.test3.service; /** * Created by heyutao on 15/11/9. */ public i...
  • HEYUTAO007
  • HEYUTAO007
  • 2015年11月09日 15:24
  • 84428

java动态代理的两种实现方式

一说到动态代理,我们第一个想到肯定是大名鼎鼎的Spring AOP了。在AOP的源码中用到了两种动态代理来实现拦截切入功能:jdk动态代理和cglib动态代理。两种方法同时存在,各有优劣。jdk动态...
  • zy_281870667
  • zy_281870667
  • 2016年11月18日 15:45
  • 1099

Java动态代理的实现

概念         代理模式        代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息...
  • futaoadmin
  • futaoadmin
  • 2016年08月12日 17:41
  • 375

Java的两种动态代理方式

动态代理指被代理者委托代理者完成相应的功能,是拦截器的一种实现方式,其用于拦截类或接口,内部可通过判断实现对某个方法的拦截。   jdk方式,委托类必须实现接口,代理类只能对接口进行代理。使用jav...
  • zilong0536
  • zilong0536
  • 2016年11月12日 17:28
  • 1086

一篇文章彻底搞懂java动态代理的实现

网上有太多文章介绍动态代理是什么,这里就不介绍了,本文目的是让大家弄懂动态代理是如何做到这些神奇的功能的。先来一个小demo,通过这个demo来讲解,动态代理需要三个类: 一个接口类; 一个实现接口的...
  • zqz_zqz
  • zqz_zqz
  • 2017年12月22日 00:17
  • 68

Java注解的部分实现:动态代理

之前一直有一个疑问:在我们获取方法、属性、类、包等等(java.lang.annotation.ElementType枚举类里面的值代都可以)的注解之后,就可以直接通过注解的方法来获取其对应的属性,但...
  • github_34160016
  • github_34160016
  • 2016年04月11日 18:18
  • 1120

java 动态代理实现原理

上篇讲了:java动态代理浅析  这篇讲讲其内部实现原理。 1、相关的类和接口 1.1 java.lang.reflect.Proxy 这是 Java 动态代理机制的主类,它提供了一组静态方法来为...
  • hla199106
  • hla199106
  • 2015年07月10日 21:08
  • 2107

代理模式及Java实现动态代理

代理模式 定义:给某个对象提供一个代理对象,并由代理对象控制对于原对象的访问,即客户不直接操控原对象,而是通过代理对象间接地操控原对象。 代理模式UML图 在上图中: RealSu...
  • GarfieldEr007
  • GarfieldEr007
  • 2016年12月18日 18:25
  • 666

JDK动态代理为什么必须针对接口

JDK动态代理为什么必须针对接口?其与CGLIB的对比 示例代码: public interface AopService {   public void doService(...
  • zanglianggo
  • zanglianggo
  • 2015年06月03日 23:44
  • 4370
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java 动态代理实现
举报原因:
原因补充:

(最多只允许输入30个字)