动态代理
- 特点: 字节码随用随创建,随用随加载
- 作用: 不修改源码的基础上对方法增强
- 分类
- 基于接口的动态代理
- 涉及的类:Proxy
- 提供者:JDK官方
- 如何创建代理对象:用Proxy类中的newProxyInstance方法
- 创建代理对象的要求:被代理对象至少实现一个接口,如果没有就不能使用
- 基于接口的动态代理
/*
这是一个需要增强的类,实现了IProduce接口
*/
public Class Produce implement IProduce{
public void sale(float money){
System.out.println("销售额为" + money);
}
public void afterSale(){
System.out.println("售后");
}
}
/*
消费者类
*/
public Class Client{
/*
该方法的参数说明:
1. ClassLoader:类加载器,用于加载代理对象字节码,和被代理对象使用相同类的加载器,固定写法
2. Class[]:字节码数组,用于代理对象和被代理对象有相同方法,固定写法
3. InvocationHandler:用于提供增强方法,它是让我们写如何代理。我们一般写该接口的实现类
通常情况下是用匿名内部类,但不是必须的,此接口的实现类是谁用谁写。
*/
public static void main(String[] args) {
final Produce produce = new Produce();
IProduce produceProxy = (IProduce)Proxy.newProxyInstance(produce.getClass().getClassLoader(),
produce.getClass().getInterfaces(),
new InvocationHandler() {
/*
执行被代理对象的任何接口方法都经过该方法
该方法的参数说明:
1. Object:被代理的对象
2. Method:当前执行的方法
3. Object[]:当前执行的方法上的参数数组
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object returnValue = null;
//1. 获取方法执行的参数
Float money = (Float)args[0];
//2.判断当前方法是否为当前需要增强的方法
if("sale".equals(method.getName())){
returnValue = method.invoke(produce,money*0.8f);
}
return returnValue;
}
});
produceProxy.sale(1000);
}
控制台输出情况
2. 基于子类的动态代理
- 特点: 字节码随用随创建,随用随加载
- 作用: 不修改源码的基础上对方法增强
- 分类
- 涉及的类:Enhanser
- 提供者:第三方cglib库
- 如何创建代理对象:用Enhanser类中的create方法
- 创建代理对象的要求:被代理对象不能是最终类
<!--在pom文件中导入该坐标-->
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.0</version>
</dependency>
/*
这是一个需要增强的类
*/
public Class Produce{
public void sale(float money){
System.out.println("销售额为" + money);
}
public void afterSale(){
System.out.println("售后");
}
}
public class TestDelegateBaseClass {
public static void main(String[] args) {
final ProduceImpl produce = new ProduceImpl();
/**
* create方法参数说明:
* 1. Class:指定被代理的对象字节码
* 2. Callback:用于提供增强的代码
* 它是让我们写如何代理。我们一般都是写一些该接口的实现类,同通常写的是匿名内部类,但不是必须的
* 我们一般写的都是该接口的子接口实现类:MethodInterceptor
*/
ProduceImpl cglibProduce = (ProduceImpl)Enhancer.create(produce.getClass(), new MethodInterceptor() {
/**
* 执行被代理对象任何方法都经过该方法
* 以下三个参数和基于接口动态代理involk方法是一样的
* @param proxy
* @param method
* @param args
* 当前执行方法的代理对象
* @param methodProxy
* @return
* @throws Throwable
*/
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object returnValue = null;
Float money = (Float)args[0];
if (method.getName().equals("sale"))
returnValue = method.invoke(produce,money*0.8f);
return returnValue;
}
});
cglibProduce.sale(1200);
}
}
运行报错 后来发现是cglib库的版本问题 改成2.1运行就有用了