代码增强之动态代理

动态代理

  • 特点: 字节码随用随创建,随用随加载
  • 作用: 不修改源码的基础上对方法增强
  • 分类
    1. 基于接口的动态代理
      - 涉及的类: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运行就有用了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值