动态代理
使用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秒
飞机颜色为:天空蓝