纵有疾风起
人生不言弃

设计模式学习笔记—代理模式Proxy(Java版)

一、场景

明星的经纪人

二、实质

通过代理控制对对象的访问。可以详细控制访问某个(某类)对象的方法,在调用这个方法之前做前置处理,调用这个方法后做后置处理。

AOP的核心实现机制。

三、角色

抽象角色–定义代理角色和真实角色的公共对外方法

真实角色–实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。关注真正的业务逻辑。(相当于明星)

代理角色–实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法实现抽象方法,并可以附加自己的操作。将统一的流程控制放到代理角色中处理。

(相当于经纪人)

四、分类

静态代理(静态定义代理类)

动态代理(动态生成代理类)

JDK自带的动态代理

javassist字节码操作库实现

CGIB

ASM

五、示例

1、静态代理

设计模式学习笔记—代理模式Proxy(Java版)插图

案例一

package com.lgd.proxy;

public interface Star {
	void confer();//面谈
	void signContract();//签合同
	void bookTicket();//订票
	void sing();//唱歌
	void collectMoney();//收钱
}

package com.lgd.proxy;

public class RealStar implements Star{

	@Override
	public void confer() {
		System.out.println("realstar.confer()");		
	}

	@Override
	public void signContract() {
		System.out.println("realstar.signContract()");		
	}

	@Override
	public void bookTicket() {
		System.out.println("realstar.bookTicket()");		
	}

	@Override
	public void sing() {
		System.out.println("realstar(@@@beyond@@@).sing()");
	}

	@Override
	public void collectMoney() {
		System.out.println("realstar.collectMoney()");
	}
	
}

package com.lgd.proxy;

public class ProxyStar implements Star{
	private Star star;
	
	public ProxyStar(Star star) {
		super();
		this.star = star;
	}

	@Override
	public void confer() {
		System.out.println("proxystar.confer()");
	}

	@Override
	public void signContract() {
		System.out.println("proxystar.signContract()");
	}

	@Override
	public void bookTicket() {
		System.out.println("proxystar.bookTicket()");		
	}

	@Override
	public void sing() {
		star.sing();
	}

	@Override
	public void collectMoney() {
		System.out.println("proxystar.collectMoney()");
	}

}

package com.lgd.proxy;

public class Client {
	public static void main(String[] args) {
		Star realStar = new RealStar();
		Star proxyStar = new ProxyStar(realStar);
		proxyStar.confer();
		proxyStar.signContract();
		proxyStar.bookTicket();
		proxyStar.sing();
		proxyStar.collectMoney();
	}
}

运行结果:

proxystar.confer()
proxystar.signContract()
proxystar.bookTicket()
realstar(@@@beyond@@@).sing()
proxystar.collectMoney()

案例二

package Thread;

/**
 * 静态代理设计模式
 * 1、真实角色
 * 2、代理角色  持有真实角色的引用
 * 3、二者要实现相同的接口
 */
public class Demo02 {
	public static void main(String[] args) {
		//创建真实角色
		You you = new You();
		//创建代理角色 + 加入真实角色的引用
		WeddingCompany company = new WeddingCompany(you);//
		//执行任务
		company.marry();	
	}	
}

//接口
interface Marry
{
	public abstract void marry();
}

//真实角色
class You implements Marry{
	@Override
	public void marry() {
		System.out.println("今天你要嫁给我。。。");
	}	
}

//代理角色
class WeddingCompany implements Marry{
	private Marry you;
	
	public WeddingCompany() {
	}
	public WeddingCompany(Marry you) {
		super();
		this.you = you;//使用真实角色对其初始化
	}
	private void before(){
		System.out.println("婚前布置会场");
	}	
	
	private void after(){
		System.out.println("婚后打扫清洁");
	}	
	
	@Override
	public void marry() {
		before();
		you.marry();
		after();
	}	
}

运行结果:

婚前布置会场
今天你要嫁给我。。。
婚后打扫清洁

静态代理的特点

优点:

可以做到在不修改目标对象的功能前提下,对目标对象功能扩展。


缺点:

因为代理对象,需要与目标对象实现一样的接口。所以会有很多代理类,类太多。

一旦接口增加方法,目标对象与代理对象都要维护。

解决:

代理工厂?  可以使用动态代理。

2、动态代理(dynamic proxy)

1)代理对象,不需要实现接口;

2)代理对象的生成,是利用JDK API, 动态的在内存中构建代理对象(需要我们指定创建 代理对象/目标对象 实现的接口的类型;);

3)  动态代理也叫JDK代理或 接口代理;

JDK自带的动态代理

java.lang.reflect.Proxy  作用:动态生成代理类和对象。

java.lang.reflect.InvocationHandler(处理器接口)  通过invoke方法对真实角色的代理访问。每次通过Proxy生成代理类对象时都要制定对应的处理器对象。


实例一:

package com.lgd.dynamicproxy;

public interface Star {
	void confer();//面谈
	void signContract();//签合同
	void bookTicket();//订票
	void sing();//唱歌
	void collectMoney();//收钱
}

package com.lgd.dynamicproxy;

public class RealStar implements Star{

	@Override
	public void confer() {
		System.out.println("realstar.confer()");		
	}

	@Override
	public void signContract() {
		System.out.println("realstar.signContract()");		
	}

	@Override
	public void bookTicket() {
		System.out.println("realstar.bookTicket()");		
	}

	@Override
	public void sing() {
		System.out.println("realstar(@@@beyond@@@).sing()");
	}

	@Override
	public void collectMoney() {
		System.out.println("realstar.collectMoney()");
	}
	
}

package com.lgd.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class StarHandler implements InvocationHandler{

	Star realStar;
	
	public StarHandler(Star realStar) {
		super();
		this.realStar = realStar;
	}

	/**
	 * 核心方法    做统一的流程控制
	 * 代理类的任何方法都来这里报到。
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object object = null;
		System.out.println("真正的方法执行前!");
		System.out.println("面谈,签合同,预付款,订机票");
		if(method.getName().equals("sing"))
		{
			object = method.invoke(realStar, args);
		}
		System.out.println("真正的方法执行后!");
		System.out.println("收钱");
		return object;
	}

}

package com.lgd.dynamicproxy;

import java.lang.reflect.Proxy;

public class Client {
	public static void main(String[] args) {
		Star realStar = new RealStar();
		StarHandler handler = new StarHandler(realStar);
		
		Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), 
				new Class[]{Star.class}, handler);
		//proxy.bookTicket();
		proxy.sing();
	}
}

运行结果:

真正的方法执行前!
面谈,签合同,预付款,订机票
realstar(@@@beyond@@@).sing()
真正的方法执行后!
收钱

实例二

public interface IUserDao {

    public void save();

}

public class UserDao implements  IUserDao {
    @Override
    public void save() {
        System.out.println("目标对象save方法");
    }
}

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Objects;

/**
 * Created by liguodong on 2015/11/10.
 */
public class ProxyFactory {

    //维护一个目标对象
    private Object target;

    public ProxyFactory(Object target){
        this.target = target;
    }
    //给目标对象生成代理对象
    public Object getFactoryInstance(){
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler(){
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("开启事务");
                        //执行目标对象
                        Object returnValue = method.invoke(target,args);
                        System.out.println("开启事务");
                        return returnValue;
                    }
                });
    }
}

public class Main {

    public static  void main(String[] args) {
        //目标对象
        IUserDao target = new UserDao();
        System.out.println(target);
        //给目标对象创建代理对象
        IUserDao proxy = (IUserDao) new ProxyFactory(target).getFactoryInstance();

        proxy.save();
    }
}

运行结果:

UserDao@19ce060
开启事务
目标对象save方法
开启事务

动态代理总结:

代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理。

六、应用场景

安全代理:屏蔽对真实角色的直接访问。

远程代理:通过代理类处理远程方法调用(RMI)。

延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象。

原文链接:https://blog.csdn.net/scgaliguodong123_/article/details/44025531

本站声明:网站内容来源于网络,如有侵权,请联系我们,我们将及时处理。

未经允许不得转载:起风网 » 设计模式学习笔记—代理模式Proxy(Java版)
分享到: 生成海报

评论 抢沙发

评论前必须登录!

立即登录