关于代理模式的那些事

代理(Proxy)模式:

代理模式是一种设计模式,其提供了对目标对象的另外的访问形式,由代理对象控制对原对象的引用.(有序类似于我们生活中的中介的意味)

举例说明,就像经纪人与明星的关系.我们如果想要邀请一位明星,可以通过找其经纪人来实现目的,明星只需负责表演即可,而其它琐事都可由经纪人代理完成.
代理对象是对目标对象的扩展,并会调用目标对象.

静态代理:

静态代理在使用时需要定义接口或父类,然后被代理对象和代理对象要共同实现接口或继承父类.
代码实现:

package proxy;
/**
 * 接口
 * @author Mr.Li
 *
 */
public interface Act {
	
	void act();
	
}
package proxy;
/**
 * 被代理对象
 * @author Mr.Li
 *
 */
public class Star implements Act{

	@Override
	public void act() {
		System.out.println("唱歌");
	}

}
package proxy;
/**
 * 静态代理对象
 * @author Mr.Li
 *
 */
public class Broker implements Act{
	//接收需代理对象
	private Star star;
	public Broker(Star star) {
		this.star = star;
	}

	@Override
	public void act() {
		System.out.println("开始活动");
		star.act();//执行对象方法
		System.out.println("活动结束");
	}

}

package proxy;
/**
 * 测试
 * @author Mr.Li
 *
 */
public class Test {
	public static void main(String[] args) {
		//定义目标对象
		Star star=new Star();
		//将目标对象传于代理对象,建立二者代理关系
		Broker broker=new Broker(star);
		//执行代理对象中的方法
		broker.act();
	}
}

静态代理总结

优点:可以做到对目标对象进行功能扩展,且符合开不原则;

缺点:我们得为每一个服务都得创建代理类,工作量太大,不易管理。同时接口一旦发生改变,代理类也得相应修改.

动态代理:

动态代理的特点:
1.代理对象不需要实现接口;
2.代理对象是利用JDK的API动态地在内存中进行构建,但需要我们指定创建代理对象/目标对象实现的接口的类型;
Java动态代理机制中有两个重要的类和接口Proxy(类)和InvocationHandler(接口),二者是我们实现动态代理的核心.
InvocationHandler接口是proxy代理实例的调用处理程序实现的一个接口,每一个proxy代理实例都有一个关联的调用处理程序.在代理实例调用方法时,方法调用被编码分派到调用处理程序的invoke方法.
每一个动态代理类的调用处理程序都必须实现InvocationHandler接口,并且每个代理类的实例都关联到了实现该接口的动态代理类调用处理程序中,当我们通过动态代理对象调用一个方法时候,这个方法的调用就会被转发到实现InvocationHandler接口类的invoke方法来调用.

    /**
    * proxy:代理类代理的真实代理对象com.sun.proxy.$Proxy0
    * method:我们所要调用某个对象真实的方法的Method对象
    * args:指代代理对象方法传递的参数
    */
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;

Proxy类就是用来创建一个代理对象的类,它提供了很多方法,但是我们最常用的是newProxyInstance方法.

    public static Object newProxyInstance(ClassLoader loader, 
                                            Class<?>[] interfaces, 
                                            InvocationHandler h)

这个方法的作用就是创建一个代理类对象,它接收三个参数,我们来看下几个参数的含义:

ClassLoader loader,:指定当前目标对象使用类加载器,获取加载器的方法是固定的
Class<?>[] interfaces,:目标对象实现的接口的类型,使用泛型方式确认类型
InvocationHandler h:事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入

作者:随风yy
来源:CSDN
原文:https://blog.csdn.net/yaomingyang/article/details/80981004
动态代理总结:
代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理.

Cglib代理:

上面的静态代理和动态代理模式都是要求目标对象是实现一个接口的目标对象,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候就可以使用以目标对象子类的方式类实现代理,这种方法就叫做:Cglib代理.

Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展.

  • JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口,如果想代理没有实现接口的类,就可以使用Cglib实现.
  • Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口.它广泛的被许多AOP的框架使用,例如Spring AOP和synaop,为他们提供方法的interception(拦截)
  • Cglib包的底层是通过使用一个小而块的字节码处理框架ASM来转换字节码并生成新的类.不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉.

Cglib子类代理实现方法:
1.需要引入cglib的jar文件,但是Spring的核心包中已经包括了Cglib功能,所以直接引入pring-core-3.2.5.jar即可.
2.引入功能包后,就可以在内存中动态构建子类
3.代理的类不能为final,否则报错
4.目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
在Spring的AOP编程中:
如果加入容器的目标对象有实现接口,用JDK代理
如果目标对象没有实现接口,用Cglib代理

作者:岑宇
出处:http://www.cnblogs.com/cenyu/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值