码迷,mamicode.com
首页 > 其他好文 > 详细

代理模式

时间:2020-02-13 17:22:39      阅读:59      评论:0      收藏:0      [点我收藏+]

标签:port   jar包   color   etc   div   cer   bsp   invoke   类加载器   

基本类图

技术图片

 

静态代理

Client.java文件

package com.waibizi.static_proxy;
public class Client {
    public static void main(String[] args) {
        //创建目标对象,也就是被代理的对象
        Dao dao = new Dao();
        //创建代理对象,并将被代理的对象传入进去
        DaoProxy daoProxy = new DaoProxy(dao);
        //通过代理对象调用代理对象的方法
        //实际上是调用了代理对象之后,由代理对象内部去调用目标对象的方法
        daoProxy.operation();
    }
}

Dao.java文件

package com.waibizi.static_proxy;
//目标对象
public class Dao implements IDao{
    @Override
    public void operation() {
        System.out.println("真正的功能");
    }
}

DaoProxy.java文件

package com.waibizi.static_proxy;
//代理对象
public class DaoProxy implements IDao{
    private IDao dao;
    public DaoProxy(IDao dao) {
        this.dao=dao;
    }
    @Override
    public void operation() {
        System.out.println("开始代理!!");
        dao.operation();
        System.out.println("代理完成");
    }

}

Idao.java文件

package com.waibizi.static_proxy;
//接口
public interface IDao {
    public void operation();
}

 

动态代理

Client.java文件

package com.waibizi.dynamic_proxy;
import static sun.misc.ProxyGenerator.generateProxyClass;

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

//动态代理

public class Client {
    public static void main(String[] args) {
        //创建目标对象,也就是被代理的对象
        IDao dao = new Dao();
        //给目标对象创建代理对象,可以转为Idao
        IDao daoProxy=(IDao) new ProxyFactory(dao).getProxyInstance();
        //System.out.println(dao.toString());
        
        
        daoProxy.operation();
        
        
        
        //比对daoProxy究竟是什么
        System.out.println(daoProxy instanceof Proxy);
        
        
      
    }
}

Dao.java文件

package com.waibizi.dynamic_proxy;


//目标对象
public class Dao implements IDao{
    @Override
    public void operation() {
        System.out.println("真正的功能");
    }
}

IDao.java文件

package com.waibizi.static_proxy;
//接口
public interface IDao {
    public void operation();
}

为了防止代码阅读性太差,这里把代理抽取出来单独调用

ProxyFactory.java文件

package com.waibizi.dynamic_proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * 
 * @author waibizi
 *
 *原理:代理类也是一个类,一个类的本质,不就是先从一个.java的后缀文件,转换成.class文件,然后再编译转换为我们的对象二进制流
 *那么,追根到底还是一个文件,我们只需要把文件生成出来,后缀名改为.java,里面的内容变成动态的
 *分析文件:
 *    一个java文件有什么
 *    package内容
 *    import内容
 *    ......
 *等等,这些无非都是字符串,万物皆对象,传进来一个Object,进行读取里面的内容,动态生成一个专属的类,即可
 */
public class ProxyFactory {
    //维护目标对象
    private Object target;
    public ProxyFactory(Object target) {
        this.target=target;
    }
    //给目标对象生成代理对象
    public Object getProxyInstance() {
        
        /**
         *    动态代理:
         *  作用:在不改变源码的情况下,对已有的方法进行增强
         *  特点:字节码随用随创建,随用随加载
         *  分类:基于接口的动态代理
         *  基于子类的动态代理
         *  基于接口的动态代理:
         *  要求:被代理类至少实现一个接口
         *  涉及类:proxy
         *  提供者:jdk
         *  创建对象的方法:newProxyInstance
         *  方法的参数:
           *    类加载器:ClassLoader,加载代理对象字节码,和被代理对象用一个类加载器
         *  字节码数组:Class[] 代理对象和被代理对象要具有相同的行为,实现相同接口
         *      如果被代理对象是一个实现类:对象.getClass().getinterfaces()
         *      如果被代理对象是一个接口:new Class[]{interface}
         *  增强方法的接口:InvocationHandler,如何增强,如何代理
         */
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    /**
                     * proxy:代理对象
                     * method:正在调用的方法 
                     * args[]:正在调用的方法的实际参数 
                     */
                    public Object invoke(Object proxy,
                            Method method,Object[] args) 
                                    throws Exception{
                        System.out.println("JDK代理开始!!!");
                        
                        //试图打印proxy的hashCode的值,发现无法进行打印,程序会尝试重新执行执行多次(toString也不可以)
                        //!System.out.println(proxy.hashCode());
                        
                        //试图打印method,是可以打印的
                        //System.out.println(method.toString());

                        //反射机制调用目标对象的方法
                        Object value = method.invoke(target,args);
                        System.out.println("代理结束!!!");
                        return value;
                    }
                }
            ); 
        }
    }

 

cglib代理,这也是一种动态代理,只不过不是由JDK直接提供的API,需要引入包

cglib相关的jar包:链接:https://pan.baidu.com/s/1xOK_s8cZuza7ruz8ZHZWXw  提取码:d7qe

Client.java文件

package com.waibizi.cglib_proxy;

public class Client {
    public static void main(String[] args) {
        Dao dao = new Dao();
        Dao proxyFactory = (Dao)new ProxyFactory(dao).getProxyInstance();
        proxyFactory.operation();
    }
}

Dao.java文件

    package com.waibizi.cglib_proxy;
    
    public class Dao {
        public void operation() {
            System.out.println("真正的功能");
        }
    }

ProxyFactory.java文件

package com.waibizi.cglib_proxy;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class      implements MethodInterceptor{
    //维护一个目标对象    
    private Object target;
    
    public ProxyFactory(Object target) {
        this.target=target;
    }
    
    //返回代理对象,是target对象的代理对象
    public Object getProxyInstance() {
        //1.创建一个工具类
        Enhancer enhancer = new Enhancer();
        //2.设置父类
        enhancer.setSuperclass(target.getClass());
        //3.设置回调函数
        enhancer.setCallback(this);
        //4.创建子类
        return enhancer.create();
    }
    /**
     *代理对象的每个方法都会执行当前方法  拦截
     * @param proxy             代理类对象引用
     * @param method            当前执行的方法
     * @param args              执行当前方法需要的参数
     * @param methodProxy       执行当前方法的代理类对象
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object proxy,
            Method method, Object[] args,
            MethodProxy methodProxy) throws Throwable {
        System.out.println("启动cglib代理");
        Object value=method.invoke(target, args);
        System.out.println("cglib代理完成");
        return value;
    }
    
}

 

代理模式

标签:port   jar包   color   etc   div   cer   bsp   invoke   类加载器   

原文地址:https://www.cnblogs.com/waibizi/p/12303890.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!