动态代理

动态代理

使用jdk动态代理来处理

目的: 将销售数量减去20 + 不管是售价还是销售数量加上一句"销售顺利!!!"话

为什么使用动态代理好?

原因: 如果是直接在程序的方法上进行操作,只有1,2处地方修改还行,但是如果有很多处都需要修改呢?
​ 这样做改的地方太多了,并且直接改源代码不好,程序耦合性大,最好要做到不修改源代码的才好.

特点: jdk动态代理是基于接口的代理
前提条件: 被代理对象必须实现接口才行.
涉及的类: Proxy 提供者: jdk官方
如何创建代理对象: 使用Proxy类的newProxyInstance()

public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
参数含义:

ClassLoader: 类加载器 加载代理对象字节码的,需要和被代理对象使用相同的类加载器.

​ (代理谁就使用谁的类加载器)

Class[]: 字节码数组 为了让代理对象和被代理对象有相同的方法

​ (代理谁就使用谁的getClass().getInterfaces())

InvocationHandler: 这里写你要增强的方法

ICar接口类:

public interface ICar {
	/**
	 * 售价
	 */
	public void price(float price);
	
	/**
	 * 销售数量
	 */
	public void saleNum(int num);
}

Car类

public class Car implements ICar{

	@Override
	public void price(float price) {
		System.out.println("玛莎拉蒂售价:¥" + price);
	}

	@Override
	public void saleNum(int num) {
		System.out.println("玛莎拉蒂卖出: " + num);
	}

}

使用jdk动态代理

public class CarProxy {

	public static void main(String[] args) {
		Car car = new Car();
		
		//因为代理对象和被代理对象实现了相同的接口
		ICar proxyCar = (ICar)Proxy.newProxyInstance(
				car.getClass().getClassLoader(), //类加载器,需要和被代理对象一样的类加载器
				car.getClass().getInterfaces(), //接口数组,需要被代理对象一样的接口数组
				new InvocationHandler() { //实现InvocationHandler接口,写具体实现代码
					/**
					 * Object proxy: 代理对象的引用
					 * Method method: 当前执行的方法
					 * Object[] args: 当前执行方法所需要的参数
					 * return : 和被代理对象方法有相同的返回值
					 */
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						Object invoke = null;
						if (method.getName().equals("saleNum")) {
							int temp = Integer.parseInt(args[0]+"")-20;
							invoke = method.invoke(car, temp); //执行被代理对象中方法,虽然不能改变方法,但是可以改变执行的参数
						} else {
							invoke = method.invoke(car, args[0]);
						}
						System.out.println("销售顺利");
						return invoke;
					}
			
		});
		
		proxyCar.price(100);
		proxyCar.saleNum(100);
		
	}

运行结果:

玛莎拉蒂售价:¥100.0
销售顺利
玛莎拉蒂卖出: 80
销售顺利

使用cglib动态代理

目的: 为每一个方法加上创建起始时间
​ 使用cglib动态代理来处理
特点: cglib动态代理是基于子类的动态代理
前提条件: 被代理对象不能被final修饰,因为是通过继承被代理对象来实现的动态代理
涉及到的类: Enhancer 提供者: 第三方cglib库
如何创建代理对象: 使用Enhancer类中的create()
create(Class type, Callback callback)

Class:字节码用于指定被代理对象的字节码

Callback:用于提高增强的代码我们一般写该接口的子接口的实现类 MethodInterceptor

Plane类

public class Plane {
	
	public void setPlane(String name) {
		System.out.println("飞机名称为: " + name);
	}
	
	public void setColor(String color) {
		System.out.println("飞机颜色为:" + color);
	}
	
}

使用cglib动态代理

public class PlaneCglibProxy {

	public static void main(String[] args) {
		Plane plane = new Plane();
		
		//因为是基于子类的实现的动态代理,所以直接转化成父类Plane
		Plane planeProxy = (Plane)Enhancer.create(plane.getClass(), new MethodInterceptor() {
			/**
			 * cglibProxy: 代理对象的引用
			 * method: 当前执行的方法
			 * args: 当前执行方法所需的参数
			 * methodProxy: 当前执行方法的代理对象
			 * return: 和被代理对象有相同的返回值
			 */
			@Override
			public Object intercept(Object cglibProxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
				//long currentTimeMillis = System.currentTimeMillis();
				Date date = new Date();
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
				String format = sdf.format(date);
				System.out.println("该飞机该功能创建时间为:  " + format);
				Object invoke = method.invoke(plane, args[0]);
				return invoke;
			}	
		});
		
		planeProxy.setPlane("辽宁号歼30");
		planeProxy.setColor("天空蓝");
	}
}

运行结果:

该飞机该功能创建时间为:  2019年11月17日 16时14分17秒
飞机名称为: 辽宁号歼30
该飞机该功能创建时间为:  2019年11月17日 16时14分17秒
飞机颜色为:天空蓝

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值