设计模式之代理模式

代理模式的关键点:

为其他对象创建一种代理以控制对这个对象的访问

通过代理控制对象的访问,可以在这个对象调用方法之前,调用方法之后去处理/添加新的功能。 (也就是AOP微实现)
代理在原有代码乃至原业务流程都不修改的情况下,直接在业务流程中切入新代码,增加新功能, 这也和Spring的(面向切面编程)很相似

应用场景

Spring AOP、日志打印、异常处理、事务控制、权限控制等

静态代理

优点:在不修改目标对象的功能前提下,能通过代理对象对目标功能扩展
缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类
一旦接口增加方法,目标对象与代理对象都要维护

代码:

//接口类
public class UserDao{
	public void save() { System.out.println("保存数据方法");} 
}
//代理类
public class UserDaoProxy extends UserDao {
	private UserDao userDao;
	public UserDaoProxy(UserDao userDao) { 
  		this.userDao = userDao;
  	}
	public void save() {
		System.out.println("开启事物...");
		userDao.save();
		System.out.println("关闭事物...");
	} 
}
//添加完静态代理的测试类 
public class Test{
	public static void main(String[] args) {
		UserDao userDao = new UserDao();
		UserDaoProxy userDaoProxy = new UserDaoProxy(userDao);
		userDaoProxy.save();
	}
 }
动态代理

jdk代理
代码:

//接口
public interface UserDao {
  void save();
}
//接口实现类

public class UserDaoImpl implements UserDao {
	public void save() { 
		System.out.println("保存数据方法");
	}
}
// 每次生成动态代理类对象时,实现了InvocationHandler接口的调用处理器对象 
public class InvocationHandlerImpl implements InvocationHandler {
	// 这其实业务实现类对象,用来调用具体的业务方法 private Object target;
	// 通过构造函数传入目标对象
	public InvocationHandlerImpl(Object target) {
		this.target = target; 
	}
	//动态代理实际运行的代理方法
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("调用开始处理"); 
		//下面invoke()方法是以反射的方式来创建对象,第一个参数是要创建的对象,第二个是构成方法的参数,由第二个参数来决定创建对象使用哪个构造方法
		Object result = method.invoke(target, args);
		System.out.println("调用结束处理");
		return result;
	}
}
public class Test {

  public static void main(String[] args) {
		// 被代理对象
		UserDao userDaoImpl = new UserDaoImpl();
		InvocationHandlerImpl invocationHandlerImpl = new InvocationHandlerImpl(userDaoImpl);
		//类加载器
		ClassLoader loader = userDaoImpl.getClass().getClassLoader();
		Class<?>[] interfaces = userDaoImpl.getClass().getInterfaces();
		// 主要装载器、一组接口及调用处理动态代理实例
		UserDao newProxyInstance = (UserDao) Proxy.newProxyInstance(loader,
		interfaces, invocationHandlerImpl); newProxyInstance.save();
	} 
}

Cglib 代理
CGLIB动态代理和jdk代理一样,使用反射完成代理,不同的是他可以直接代理类(jdk动态代理不 行,他必须目标业务类必须实现接口),CGLIB动态代理底层使用字节码技术,CGLIB动态代理不能对 final类进行继承.(CGLIB动态代理需要导入jar包)

代码:

//接口
public interface UserDao {
	void save();
}
//接口实现类
public class UserDaoImpl implements UserDao {
	public void save() { System.out.println("保存数据方法");}
}
//代理主要类
public class CglibProxy implements MethodInterceptor {
	private Object targetObject;
	// 这里的目标类型为Object,则可以接受任意一种参数作为被代理类,实现了动态代理 
	public Object getInstance(Object target) {
		// 设置需要创建子类的类 this.targetObject = target;
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(target.getClass());
		enhancer.setCallback(this);
		return enhancer.create();
	}
	//代理实际方法
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		System.out.println("开启事物");
		Object result = proxy.invoke(targetObject, args);
		System.out.println("关闭事物");
		// 返回代理对象
		return result;
	}
}
//测试CGLIB动态代理 
public class Test {
	public static void main(String[] args) {
		CglibProxy cglibProxy = new CglibProxy();
		UserDao userDao = (UserDao) cglibProxy.getInstance(new UserDaoImpl());
		userDao.save();
	}
}

常见的代理模式

缓存(代理):当请求静态文件(图片)等资源时,可以先到缓存代理取,如果取到资源;如果取不到资源,再到公网或数据库取,然后缓存
远程(代理):远程对象的本地代表,通过它可以把远程对象当本地对象来调用。远程代理通过网络和真正的远程对象沟通信息
同步(代理):主要使用在多线程编程中,完成多线程间同步工作
防火墙(代理):内网通过代理穿透防火墙,达到对公网的访问

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值