设计模式之代理模式(Proxy Pattern)

应用场景

Proxy代理模式是一种结构型设计模式,主要解决的问题是:直接访问对象时带来的问题。

为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者并无区别。

代理类种类:

静态代理:创建代理类再对其编译,在程序运行前代理类的.class文件就已经存在了。

动态代理:在程序运行时运用反射机制动态创建而成。

一、静态代理

静态代理实现很简单,就是跟目标类实现同样的接口,然后引入目标类。在目标类方法执行前后增加额外的方法即可。

但是有个问题需要注意:每次在接口中添加一个新方法,则需要在目标对象中实现这个方法,并且在代理对象中实现相应的代理方法。

public interface ProductDao {
	//添加商品
	void add();
	//删除商品
	void delete();
	//修改商品
	void update();
	//查找商品
	void select();
}
public class ProductDaoImpl implements ProductDao {

	@Override
	public void add() {
		System.out.println("目标对象中添加商品");
	}

	@Override
	public void delete() {
		System.out.println("目标对象中删除商品");
	}

	@Override
	public void update() {
		System.out.println("目标对象中修改商品");
	}

	@Override
	public void select() {
		System.out.println("目标对象中查找商品");
	}

}
public class ProductDaoImplProxy implements ProductDao {

	private ProductDao productDao;

	public ProductDaoImplProxy(ProductDao productDao) {
		super();
		this.productDao = productDao;
	}

	@Override
	public void add() {
		System.out.println("添加商品begin");
		productDao.add();
	}

	@Override
	public void delete() {
		System.out.println("刪除商品begin");
		productDao.delete();
	}

	@Override
	public void update() {
		System.out.println("修改商品begin");
		productDao.update();
	}

	@Override
	public void select() {
		System.out.println("查找商品begin");
		productDao.select();
	}

}

 执行结果:

 二、动态代理

常见的动态代理有JDK动态代理跟Cglib动态代理

1.JDK动态代理

JDK的动态代理,是使用反射技术获得类的加载器并且创建实例,根据类执行的方法在执行方法的前后发送通知。

java.lang.reflect 包下面的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。

在代理对象Proxy的新建代理实例方法中,必须要获得类的加载器、类所实现的接口、还有一个拦截方法的句柄。然后在句柄的invoke()方法中调用method.invoke(),在此方法前后发送通知,实现功能扩展。

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

public class ProductDaoJDKProxy {

	public static void main(String[] args) {
		//目标对象
		ProductDao productDao = new ProductDaoImpl();
		//代理对象
		ProductDao proxy = (ProductDao) Proxy.newProxyInstance(
				productDao.getClass().getClassLoader(),
				productDao.getClass().getInterfaces(), 
				new InvocationHandler() {
					//拦截到目标对象的方法时执行
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						System.out.println("jdk在代理对象中拦截到方法:" + method.getName());
						proxy = method.invoke(productDao, args);
						return proxy;
					}
				});
		//代理对象调用方法
		proxy.add();
		proxy.delete();
	}

}

运行结果:

 

2.Cglib动态代理

JDK动态代理和静态代理所代理的类都是实现了某接口的,对于没有实现接口的类,可以使用Cglib动态代理。

Cglib动态代理需要引入两个jar包:asm跟cglib

CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。

注意:arg0:生成的代理对象;arg1:目标对象的方法;arg2:目标对象的方法入参

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class ProductDaoCglibProxy {

	public static void main(String[] args) {
		ProductDaoImpl target = new ProductDaoImpl();
		Enhancer enhancer = new Enhancer();
		// 设置代理对象的父类
		enhancer.setSuperclass(target.getClass());
		// 设置回调
		enhancer.setCallback(new MethodInterceptor() {
			@Override
			public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
				System.out.println("Cglib在代理对象中拦截到方法:" + arg1.getName());
				arg0 = arg1.invoke(target, arg2);
				return arg0;
			}
		});
		// 代理对象调用方法
		ProductDaoImpl proxy = (ProductDaoImpl) enhancer.create();
		proxy.add();
		proxy.delete();
	}

}

运行结果:

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值