《JAVA设计模式系列》吃透代理模式就看这一篇

代理模式

由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

代理模式的优缺点

优点

  • 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用
  • 代理对象可以扩展目标对象的功能
  • 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度

缺点

  • 在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢
  • 增加了系统的复杂度

代理模式的结构

  • Subject(共同接口):客户端使用的现有接口
  • RealSubject(真实对象):真实对象的类
  • ProxySubject(代理对象):代理类

静态代理

实现过程

  • 为要被代理的目标类型设计一个接口

  • 目标类型实现这个接口 但是只关注核心业务

  • 代理类型 同样实现这个接口

举例说明

Subject(共同接口)为要被代理的目标类型设计一个Teacher接口

public interface Teacher{
    void teach();
}

RealSubject(真实对象) 目标类型实现这个接口 但只需要关注核心业务(周老师 : 只需要使劲上课)

public class JayZhou implements Teacher{
    @Override
    public void teach(){
        System.out.println("核心业务:使劲上课");
    }
}

ProxySubject(代理对象) 代理类型同样实现这个接口(助教大白: 上课前帮老师收手机上课后帮老师看自习)

public class BigWhite implements Teacher{
    Teacher tea;//代理类型应当持有一个目标类型的对象
    public BigWhite(Teacher tea){
        this.tea = tea;
    }

    @Override
    public void teach(){
        System.out.println("前置非核心:收手机");
        tea.teach();//邀请核心执行  大白邀请周老师讲课
        System.out.println("后置非核心:看自习");
    }
}

客户端

public class Test{
    public static void main(String[] args){
        JayZhou jay = new JayZhou();
        BigWhite db = new BigWhite(jay);
        db.teach();
    }
}

动态代理

  • 静态代理已经足以指向核心和非核心编码层面的解耦

  • 但是 编码层面付出很大 假如 要被代理的是100个类 当中的500个方法 写死你!

基于JDK的动态代理

public interface Teacher {
    Object teach();
}
public class JayZhou implements Teacher{
    @Override
    public Object teach(){
        System.out.println("核心业务:使劲上课~");
        return null;
    }
}
public class TestJDKDynamicProxy {

	public static void main(String[] args) {
		JayZhou jay = new JayZhou();//要被代理的目标对象
		//代理工具类.新建一个代理类的实例
	
		//	1st.ClassLoader对象 = 类加载器对象
		//	jay.getClass().getClassLoader()
		//	2nd.Class[] 代理类要实现哪些接口 
		//  new Class[]{Teacher.class} //愚蠢的写法
		//	jay.getClass().getInterfaces()
		//	3rd.InvocationHandler 调用控制器		
	
		Teacher db = (Teacher)Proxy.newProxyInstance(
				jay.getClass().getClassLoader(),
				jay.getClass().getInterfaces(),
				new InvocationHandler(){
					@Override
					public Object invoke(Object obj, Method m, Object[] args)
							throws Throwable {
						System.out.println("==前置非核心:收手机==");
						Object ok = m.invoke(jay, args);
						System.out.println("==后置非核心:看自习==");
						return ok;
					}
				});	
		Object obj = db.teach();	
	}
}

基于CGLIB 的动态代理

需要引入JAR包

public class TestCGLIBDynamicProxy {

	public static void main(String[] args) {
		JayZhou jay = new JayZhou();
		Enhancer en = new Enhancer(); 
		en.setSuperclass(jay.getClass());
		en.setCallback(new MethodInterceptor(){
			@Override
			public Object intercept(Object obj, Method m, Object[] args,
					MethodProxy mp) throws Throwable {
				System.out.println("==前置非核心:收手机==");
				//Object ok = m.invoke(jay, args);
				Object ok = mp.invokeSuper(obj, args);
				System.out.println("==后置非核心:看自习==");
				return ok;
			}
		});
		jay = (JayZhou)en.create();
		jay.teach();
	}
}

JDK动态代理与CGLIB 动态代理的区别(面试题)

  • JDK 动态代理只能针对接口实现类生成代理实例,而不能针对类;也就是说它是面向接口的
  • CGLIB 是针对类实现代理,主要是对指定的类生成一个子类,并覆盖其中方法实现增强,但是因为采用的是继承,所以该类或方法最好不要声明成 final,对于 final 类或方法,是无法继承的

JDK动态代理与CGlab的动态代理类加载的过程

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值