Java设计模式-代理模式

一. 概述

1. 什么是代理模式?

代理模式:提供一个代理对象来控制被代理对象的访问,在客户端和原对象之前起到中介的作用

2.为什么用代理模式?

当一个对象不适合或不能直接引用另一对象时,使用代理模式可以起到隔离作用,代理类和被代理类实现相同的接口,还可以通过代理类增加额外功能来扩展被代理类,符合代码设计的开闭原则

3.代理模式的角色?

  • 抽象主题(Subject):代理类和被代理类的共同接口
  • 具体主题(RealSubject):被代理类
  • 代理主题(Proxy):代理类

二. 代理模式

1. 静态代理

抽象主题:创建一个接口

public interface IUserDao {
	void save();
}

具体主题:创建被代理类

public class UserDao implements IUserDao {
	public void save(){
		System.out.println("保存了用户");
	}
}

代理主题:创建代理类

public class ProxyUserDao implements IUserDao {
	private IuserDao iUserDao;
	//创建构造器,初始化时传入被代理对象
	//用接口类作为构造器参数,可以传入实现此接口的任何被代理类
	public ProxyUserDao(IuserDao iUserDao){
		this.iUserDao = iUserDao;
	}
	public void save(){
		System.out.println("代理方法进行一些准备工作");
		iUserDao.save();//执行被代理类中的方法
		Sytem.out.println("代理方法进行一些后续工作")	
	}
}

测试

public class ProxyTest {
	public static void main(String[] args) {
		//1.创建被代理对象
		UserDao userDao = new UserDao();
		//2.创建代理对象,用被代理对象初始化
		ProxyUserDao proxy = new ProxyUserDao(userDao);
		proxy.save();
	}
}

执行结果

代理方法进行一些准备工作
保存了用户
代理方法进行一些后续工作
  • 优点:在不改变原类代码的前提下,对其进行功能扩展
  • 缺点:越多的扩展,导致实现相同接口的代理类增多,难以维护

2. JDK 动态代理

核心代码:Proxy.newProxyInstance(类加载器,接口,InvocationHandler)

public class ProxyFactory{
	//返回一个代理类的对象
	public static Object getProxyInstance(Object obj){
		MyInvocationHandler handler = new MyInvocationHandler(obj);
		return Proxy.newProxyInstance(obj.getClass().getClassLoader(),//参数1:与被代理类相同的类加载器
									  obj.getClass().getInterfaces(),//参数2:与被代理类需要实现的相同接口
									  handler);//参数3:InvocationHandler,可以直接用匿名内部类
	}
}

class MyInvocationHandler implements InvocationHandler{
	
	private Object obj;
	
	public MyInvocationHandler(Object obj){
		this.obj = obj;
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		//(插入自定义增强代码)
		return method.invoke(obj,args);	//被代理对象中的方法
	}
}

测试

public class ProxyTest {
	public static void main(String[] args) {
		//1.创建被代理对象
		UserDao userDao = new UserDao();
		//2.创建代理对象
		IUserDao proxy = (IUserDao) ProxyFactory.getProxyInstance(userDao);
		proxy.save();	
	}
}

3. CGLIB 动态代理

对于没有接口的类,使用 CGLIB 实现动态代理
核心代码:Enhancer.create(反射类型,MethodInterceptor)

//创建拦截器
public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("准备工作");
        Object object = methodProxy.invokeSuper(o, args);
        System.out.println("后续工作");
        return object;
    }
}
public class ProxyTest {
    public static void main(String[] args) {

        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UseDao.class);
        enhancer.setCallback(new MyMethodInterceptor());

        UserDao proxy = (UserDao) enhancer.create();
        proxy.save();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值