代理模式

一、代理模式概述

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

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

动态代理有基于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);
	}

}
posted @ 2019-12-26 21:54  HeliusKing  阅读(267)  评论(0编辑  收藏  举报