静态代理和动态代理

代理模式

给某一个对象提供一个代理,并由代理对象来控制对真实对象的访问。代理模式是一种结构型设计模式。

代理模式有三种:

  • Subject(抽象主题角色):定义代理类和真实主题的公共对外方法,通常被设计成接口
  • RealSubject(真实主题角色):真正实现业务逻辑的类;
  • Proxy(代理主题角色):用来代理和封装真实主题;

代理模式的结构比较简单,其核心是代理类,为了让客户端能够一致性地对待真实对象和代理对象,在代理模式中引入了抽象层。

如果根据字节码的创建时机来分类,可以分为静态代理和动态代理:
●所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和真实主题角色的关系在运行前就确定了。
●而动态代理的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以在运行前并不存在代理类的字节码文件

一、静态代理

实现过程

1.首先定义一个接口,接口定义代理类和目标类的实现方法

public interface UserService {
	public void update();
	public void select();
}

2.创建接口的实现类

public class UserServiceImpl implements UserService{

	@Override
	public void update() {
        System.out.println("更新");
		
	}

	@Override
	public void select() {
		 System.out.println("查询");
	}

}

3.静态代理也实现该方法

public class UserServiceProxy implements UserService{
	
	private UserServiceImpl realUserService=new UserServiceImpl();
	
	@Override
	public void update() {
		long begin=System.currentTimeMillis();
		realUserService.update();
		long end=System.currentTimeMillis();
		System.out.println();
	}

	@Override
	public void select() {
		realUserService.select();
	System.out.println();
	}

}

4.测试

public interface Test {
	public static void main(String[] args) {
		
		UserServiceProxy userproxy=new UserServiceProxy();
		userproxy.select();
		System.out.println();
		userproxy.update();
		System.out.println();
    }
}

静态代理的优缺点

优点:

通过静态代理,我们达到了功能增强的目的,而且没有侵入原代码,这是静态代理的一个优点。

缺点:

虽然静态代理实现简单,且不侵入原代码,但是,当场景稍微复杂一些的时候,静态代理的缺点也会暴露出来。1、 当需要代理多个类的时候,由于代理对象要实现与目标对象一致的接口,有两种方式:只维护一个代理类,由这个代理类实现多个接口,但是这样就导致代理类过于庞大新建多个代理类,每个目标对象对应一个代理类,但是这样会产生过多的代理类2、 当接口需要增加、删除、修改方法的时候,目标对象与代理类都要同时修改,不易维护。

二、动态代理

动态代理实在运行过程中进行动态创造的,Java中两种常见的动态代理方式:JDK原生动态代理和CGLIB动态代理(第三方开源类库)。

JDK动态代理主要涉及两个类:java.lang.reflect.Proxy 和 java.lang.reflect.InvocationHandler。

JDK动态代理实现过程

动态代理处理类

public class PerformanceInvocationHandler implements InvocationHandler {
	
	private Object real;
	public PerformanceInvocationHandler(Object real) {
		this.real=real;
	}

	/**
	 * 	参数:proxy
	  *     参数:method
	 *	参数:args
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		
		long begin=System.currentTimeMillis();
		
		//真实业务对象当前执行方法基于反射方式
		Object returnValue=method.invoke(real, args);
		
		long end =System.currentTimeMillis();
		System.out.println("方法耗时"+(end-begin)+"毫秒");
		
		return returnValue;
	}

}

测试

public class Test1 {
	public static void main(String[] args) {
		//真实主题对象
		OrderServiceImpl realOrderService=new OrderServiceImpl();
		//获取类加载器
		ClassLoader loader=realOrderService.getClass().getClassLoader();
		//获取真实的类继承的接口
		//因为一个类可以实现多个接口所有用Class[] 数组接收
		Class[] interfaces=realOrderService.getClass().getInterfaces();
		
		//创建InvocationHander对象(动态代理执行的逻辑)
		PerformanceInvocationHandler h= new PerformanceInvocationHandler(realOrderService);
		
		//创建动态代理
		OrderService orderProxy=(OrderService)Proxy.newProxyInstance(loader, interfaces, h);
		orderProxy.service1(12.0, 0001);
	}
}

CGLIB动态代理

基于子类的动态代理(第三方 Cglib)CGlib方式是基于继承实现的代理,它不是指真实类需要继承某个父类,而是生成的代理类作为真实类的子类去代理父类,即代理类继承自真实类。这种方式不需实现接口,可以作为JDK代理方式的补充方案。\n\n CGLIB(Code Generation Library)是一个基于ASM(Java字节码操作框架)实现的代码生成库,它可以在运行时动态生成目标类的子类作为代理类,并覆盖其中的方法来实现代理功能。与Java自带的JDK动态代理不同,CGlib动态代理可以代理没有实现接口的类。

三、静态代理和动态代理的区别

  1. 生成方式:静态代理需要手动编写或自动生成.java源文件,而动态代理通过Java反射机制动态地创建类;
  2. 扩展性:静态代理扩展性较差,因为一旦.class文件生成就不能再改变行为,而动态代理扩展性较好,可以方便地改变行为;
  3. 代码结构:静态代理的代码结构较为简单明了,而动态代理的代码结构稍微复杂一些,需要实现InvocationHandler接口和处理Method对象;
  4. 性能:静态代理的性能略优于动态代理,因为静态代理可以提前编译成本地代码,而动态代理需要在运行时动态创建类;
  5. 适用场景:静态代理适用于简单扩展场景,而动态代理适用于复杂的扩展场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值