• 代理模式


    一、代理模式概述

    定义 :给某一个对象提供一个代理,并由代理对象控制对原对象的引用

    分类:有静态代理和动态代理之分

    动态代理有基于JDK的动态代理和基于Cglib的动态代理

    二、静态代理

    举个例子:比如找周杰伦唱歌,我们不能直接找周杰伦,我们得找他的经纪人,经纪人要签合同,付定金,唱完歌再付尾款。

    这里我们抽象出三个角色。

    唱歌:

    找周杰伦唱歌

    找经纪人唱歌,实际唱歌的还是周杰伦

    代码示例

    public interface Sing {
        //唱歌
        void sing();
    }
    
    public class JaySing implements Sing {
        @Override
        public void sing() {
            System.out.println("我是周杰伦,欢迎来找我唱歌!");
        }
    }
    
    public class AgentSing implements Sing {
    
        Sing target;
    
        public AgentSing(Sing target) {
            this.target = target;
        }
    
        @Override
        public void sing() {
            System.out.println("付定金");
            target.sing();
            System.out.println("付尾款");
        }
    }
    
    // 测试
    public class Client {
        public static void main(String[] args) {
            JaySing jaySing = new JaySing();
            AgentSing agentSing = new AgentSing(jaySing);
            agentSing.sing();
        }
    }
    

    静态代理非常简单。

    三、JDK动态代理

    代理对象,不需要实现接口,但是目标对象要实现接口,否则不能用JDK动态代理,底层是使用反射技术。

    //接口
    public interface ITeacherDao {
    
    	void teach(); // 授课方法
    	void sayHello(String name);
    }
    
    public class TeacherDao implements ITeacherDao {
    
    	@Override
    	public void teach() {
    		// TODO Auto-generated method stub
    		System.out.println(" 老师授课中.... ");
    	}
    
    	@Override
    	public void sayHello(String name) {
    		// TODO Auto-generated method stub
    		System.out.println("hello " + name);
    	}
    	
    }
    
    public class ProxyFactory {
    
    	//维护一个目标对象 , Object
    	private Object target;
    
    	//构造器 , 对target 进行初始化
    	public ProxyFactory(Object target) {
    		
    		this.target = target;
    	} 
    	
    	//给目标对象 生成一个代理对象
    	public Object getProxyInstance() {
    		
    		//说明
    		/*
    		 *  public static Object newProxyInstance(ClassLoader loader,
                                              Class<?>[] interfaces,
                                              InvocationHandler h)
                                              
                //1. ClassLoader loader : 指定当前目标对象使用的类加载器, 获取加载器的方法固定
                //2. Class<?>[] interfaces: 目标对象实现的接口类型,使用泛型方法确认类型
                //3. InvocationHandler h : 事情处理,执行目标对象的方法时,会触发事情处理器方法, 会把当前执行的目标对象方法作为参数传入
    		 */
    		return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
    				target.getClass().getInterfaces(), 
    				new InvocationHandler() {
    					@Override
    					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    						// TODO Auto-generated method stub
    						System.out.println("JDK代理开始~~");
    						//反射机制调用目标对象的方法
    						Object returnVal = method.invoke(target, args);
    						System.out.println("JDK代理提交");
    						return returnVal;
    					}
    				}); 
    	}
    	
    	
    }
    
    
    //测试
    public class Client {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		//创建目标对象
    		ITeacherDao target = new TeacherDao();
    		
    		//给目标对象,创建代理对象, 可以转成 ITeacherDao
    		ITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance();
    	
    		// proxyInstance=class com.sun.proxy.$Proxy0 内存中动态生成了代理对象
    		System.out.println("proxyInstance=" + proxyInstance.getClass());
    		
    		//通过代理对象,调用目标对象的方法
    		//proxyInstance.teach();
    		
    		proxyInstance.sayHello(" tom ");
    	}
    
    }
    

    四、Cglib代理

    public class TeacherDao {
    
    	public String teach() {
    		System.out.println(" 老师授课中  , 我是cglib代理,不需要实现接口 ");
    		return "hello";
    	}
    }
    
    
    public class ProxyFactory 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();
    		
    	}
    	
    
    	//重写  intercept 方法,会调用目标对象的方法
    	@Override
    	public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
    		// TODO Auto-generated method stub
    		System.out.println("Cglib代理模式 ~~ 开始");
    		Object returnVal = method.invoke(target, args);
    		System.out.println("Cglib代理模式 ~~ 提交");
    		return returnVal;
    	}
    
    }
    
    

    测试:

    public class Client {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		//创建目标对象
    		TeacherDao target = new TeacherDao();
    		//获取到代理对象,并且将目标对象传递给代理对象
    		TeacherDao proxyInstance = (TeacherDao)new ProxyFactory(target).getProxyInstance();
    
    		//执行代理对象的方法,触发intecept 方法,从而实现 对目标对象的调用
    		String res = proxyInstance.teach();
    		System.out.println("res=" + res);
    	}
    
    }
    
  • 相关阅读:
    微软Office团队做产品的十大经验教训 沧海
    Definitio of Business Intelligence 沧海
    爱购家园,轻松工作,轻松生活 沧海
    SAAS概述 沧海
    一定要做自己最内行的东西,一定要在自己本身的职位上来提升自己 沧海
    Android应用的构成 沧海
    管理的最高境界,就是激发每个员工的潜力。让每个员工都觉得自己的工作是一份事业。 沧海
    The life cycle of a typical project 一个典型的项目生命周期 沧海
    印度英语的特点归纳 沧海
    3G时代的移动业务赢利模式分析 沧海
  • 原文地址:https://www.cnblogs.com/heliusKing/p/12104651.html
Copyright © 2020-2023  润新知