java基础与提高系列-java 代理(静态代理和动态代理)

来源:互联网 发布:ios移动网络下上传图片 编辑:程序博客网 时间:2024/06/08 17:50

spring的核心有两大思想,一个是IOC ,一个是Aop 博主比较菜,看了半天一脸懵逼,感觉要凉就回去看java 动态代理了,所以本篇就是对java的代理机制的一个学习和回顾。

学代理发现java代理机制并没有单一,代理机制分为两种静态和动态代理,静态代理的特征是代理类和目标对象的类都是在编译期间确定下来。 下面看一下静态代理。
静态代理
1. 首先我们定义一个接口,即时静态代理的接口。

//静态代理//接口interface ClothFactory{    void productCloth();    };
  1. 接下来,定义一个被代理类实现该接口
//被代理类class NikeClothFactory implements ClothFactory{    @Override    public void productCloth() {        System.out.println("Nike 工厂 生产一批衣服");    }}
  1. 代理类
//代理类class ProxyFactory implements ClothFactory{    ClothFactory cf;    //创建代理类对象时,实际传入一个被代理类的对象    public ProxyFactory(ClothFactory cf) {        this.cf=cf;    }    @Override    public void productCloth() {        System.out.println("代理类开始执行,收代理费");        cf.productCloth();    }}

下面来解释一下步骤,定义了ClothFactory接口 以及,其中的productCloth() 方法, 然后定义NikeClothFactory 类去实现该接口来充当要被代理的类, 下面就是真正去写我们要用的方法以及类(就是代理类ProxyFactory,当然该类必须实现我们的接口, 然后定义接口引用,在创建代理对象的时候实际传入一个被代理的对象(接口的内容,不再赘述)

下面就是测试代码:

public class TestClothProduct {      public static void main(String[] args) {          NikeClothFactory nike=new NikeClothFactory();          ProxyFactory proxy=new ProxyFactory(nike);          proxy.productCloth();    }}

用代理类的方法去执行我们想要执行的方法
由上我们能发现 每一个代理类只能为一个接口服务,这样一来程序开发中必然产生过多的代理,所以,不利于程序的扩展。
静态全部代码:

package com.aixscode.java.teststatic;//静态代理//接口interface ClothFactory{    void productCloth();    };//被代理类class NikeClothFactory implements ClothFactory{    @Override    public void productCloth() {        System.out.println("Nike 工厂 生产一批衣服");    }}//代理类class ProxyFactory implements ClothFactory{    ClothFactory cf;    //创建代理类对象时,实际传入一个被代理类的对象    public ProxyFactory(ClothFactory cf) {        this.cf=cf;    }    @Override    public void productCloth() {        System.out.println("代理类开始执行,收代理费");        cf.productCloth();    }}public class TestClothProduct {      public static void main(String[] args) {          NikeClothFactory nike=new NikeClothFactory();          ProxyFactory proxy=new ProxyFactory(nike);          proxy.productCloth();    }}

动态代理
动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。
其实代理不是关键,要理解代理模式的原理:
使用一个代理将对象包装起来,然后用该代理对象取出原始对象,任何对原始对象的调用都要通过代理,代理对象决定是否以及何时将方法调用转到原始对象上。

Proxy 专门完成代理的操作类,是所有动态代理类的父类,通过此类为一个或者多个接口动态生成实现类。

提供用于创建动态代理类和动态代理对象的静态方法。

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

loader : 类的加载器
interface : 得到全部接口
InvocationHandler h : 得到invocationHandler 接口的子类实例

下面看一下具体代码:
1. 和静态类似,

//动态代理的使用,体会反射是动态语言的关键interface Subject {    void action();}
  1. 创建被代理类
// 被代理类class RealSubject implements Subject {    public void action() {        System.out.println("我是被代理类,记得要执行我哦!么么~~");    }}
  1. 是核心代码 ,创建MyInvocationHandler 实现InvocationHandler
    创建实现了接口的被代理的对象的声明这里创建Object 类型,再给被代理的对象实例化。
class MyInvocationHandler implements InvocationHandler {    Object obj;// 实现了接口的被代理类的对象的声明    // ①给被代理的对象实例化②返回一个代理类的对象    public Object blind(Object obj) {        this.obj = obj;        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj                .getClass().getInterfaces(), this);    }    //当通过代理类的对象发起对被重写的方法的调用时,都会转换为对如下的invoke方法的调用    @Override    public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable {        //method方法的返回值时returnVal        Object returnVal = method.invoke(obj, args);        return returnVal;    }}

然后是测试

public class TestProxy {    public static void main(String[] args) {        //1.被代理类的对象        RealSubject real = new RealSubject();        //2.创建一个实现了InvacationHandler接口的类的对象        MyInvocationHandler handler = new MyInvocationHandler();        //3.调用blind()方法,动态的返回一个同样实现了real所在类实现的接口Subject的代理类的对象。        Object obj = handler.blind(real);        Subject sub = (Subject)obj;//此时sub就是代理类的对象        sub.action();//转到对InvacationHandler接口的实现类的invoke()方法的调用        //再举一例        NikeClothFactory nike = new NikeClothFactory();        ClothFactory proxyCloth = (ClothFactory)handler.blind(nike);//proxyCloth即为代理类的对象        proxyCloth.productCloth();    }}

下面贴出全部代码

package com.aixscode.java.teststatic;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;//动态代理的使用,体会反射是动态语言的关键interface Subject {    void action();}// 被代理类class RealSubject implements Subject {    public void action() {        System.out.println("我是被代理类,记得要执行我哦!么么~~");    }}class MyInvocationHandler implements InvocationHandler {    Object obj;// 实现了接口的被代理类的对象的声明    // ①给被代理的对象实例化②返回一个代理类的对象    public Object blind(Object obj) {        this.obj = obj;        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj                .getClass().getInterfaces(), this);    }    //当通过代理类的对象发起对被重写的方法的调用时,都会转换为对如下的invoke方法的调用    @Override    public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable {        //method方法的返回值时returnVal        Object returnVal = method.invoke(obj, args);        return returnVal;    }}public class TestProxy {    public static void main(String[] args) {        //1.被代理类的对象        RealSubject real = new RealSubject();        //2.创建一个实现了InvacationHandler接口的类的对象        MyInvocationHandler handler = new MyInvocationHandler();        //3.调用blind()方法,动态的返回一个同样实现了real所在类实现的接口Subject的代理类的对象。        Object obj = handler.blind(real);        Subject sub = (Subject)obj;//此时sub就是代理类的对象        sub.action();//转到对InvacationHandler接口的实现类的invoke()方法的调用        //再举一例        NikeClothFactory nike = new NikeClothFactory();        ClothFactory proxyCloth = (ClothFactory)handler.blind(nike);//proxyCloth即为代理类的对象        proxyCloth.productCloth();    }}