静态代理和动态代理

一、什么是代理
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.
这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法
在这里插入图片描述
代理模式的关键点是:代理对象与目标对象,代理对象是对目标对象的扩展,并会调用目标对象

二、静态代理
简单看一个静态代理的例子

静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类.

接口

public interface UserDao {
	void save();
}

被代理对象

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

代理对象

public class UserDaoProxy implements UserDao {

	private UserDao userDao;
	public UserDaoProxy(UserDao target) {
		this.userDao = target;
	}

	@Override
	public void save() {
		System.out.println("保存之前的操作...");
		userDao.save();
		System.out.println("保存之后的操作...");

	}
}

使用代理对象

/**
 * @author chengxn
 * @date 2019/3/28
 * 静态代理优点:可以做到在不修改目标对象的功能前提下,对目标功能扩展.
 * 缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.
 */
public class StaticProxyMain {
	public static void main(String[] arg){
		//新建目标对象 传给代理对象  代理对象调用save(代理对象内部会调用目标对象的方法)
		UserDaoProxy proxy = new UserDaoProxy(new UserDaoImpl());
		proxy.save();
	}
}

运行结果
在这里插入图片描述
三、动态代理
在动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class)

① InvocationHandler

该接口是proxy代理实例的调用处理程序实现的一个接口,
每一个proxy代理实例都有一个关联的调用处理程序;在代理实例调用方法时,方法调用被编码分派到调用处理程序的invoke方法。

我们需要实现调用处理程序的invoke方法,在方法中扩展原有方法做额外的操作(这里用到了Java反射机制
每个代理类的实例都关联到了实现该接口的动态代理类调用处理程序中,当我们通过动态代理对象调用一个方法时候,这个方法的调用就会被转发到实现InvocationHandler接口类的invoke方法来调用。

② Proxy

Proxy类就是用来创建一个代理对象的类,它提供了很多方法,但是我们最常用的是newProxyInstance方法(返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序)。

下面看具体使用

接口

public interface UserDao {
	void save();
}

被代理对象

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

调用处理程序

public class MyInvocationHandler implements InvocationHandler {

	private Object object;

	public MyInvocationHandler(Object object) {
		this.object = object;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("执行前");
		method.invoke(object, args);
		System.out.println("执行后");
		return null;
	}

}

创建代理对象并调用

public class DynamicProxyMain {

	public static void main(String[] args){
		UserDao userDao = new UserDaoImpl();
		InvocationHandler invocationHandler = new MyInvocationHandler(userDao);

        //创建代理对象
        //参数详解:public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, 
        //                                   InvocationHandler h)
        //①loader:一个classloader对象,定义了由哪个classloader对象对生成的代理类进行加载
        //②interfaces:一个interface对象数组,表示我们将要给我们的代理对象提供一组什么样的接口,
        //如果我们提供了这样一个接口对象数组,那么也就是声明了代理类实现了这些接口,代理类就可
        //以调用接口中声明的所有方法。 
        //③h:一个InvocationHandler对象,表示的是当动态代理对象调用方法的时候会关联到哪一个
        //InvocationHandler对象上,并最终由其调用
        
		UserDao proxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(),
				userDao.getClass().getInterfaces(),invocationHandler);
		proxy.save();
	}


}

运行结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值