栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spring-动态代理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring-动态代理

spring-动态代理
  • 1.动态代理
  • 2.jdk动态代理
  • 3.CGLIB动态代理
  • 4.动态代理的作用
  • 5.jdk动态代理实现步骤

1.动态代理

       动态代理是指,程序在整个运行过程中根本就不存在目标类的代理类,目标对象的代理对象只是由代理生成工具(不是真实定义的类)在程序运行时由JVM根据反射等机制动态生成的。代理对象与目标对象的代理关系在程序运行时才成立。

2.jdk动态代理

       动态代理的实现方式常用的有两种:使用JDK的proxy,与通过CGLIB生成代理。
       jdk的动态要求目标对象必须实现接口,这是java设计上的要求。
       从jdk1.3以来,jdk语言通过java.lang.reflect包提供了三个类支持代理模式Proxy,Method和InovcationHandler。

3.CGLIB动态代理

       CGLib (Code Generation Library) 是一个开源项目。是一个强大的,高性能,高质量的Code生成库,它可以在运行期扩展java类与实现java接口。它广泛的被许多AOP的框架使用,例如Spring AOP。
       使用JDK的proxy实现代理,要求目标类与代理类实现相同的接口。若目标类不存在接口,则无法使用该方法实现。但对于无接口的类,要为其创建动态代理,就要使用CGLIB来实现。
       CGLIB代理的生成原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理对象。所以,使用CGLIB生成动态代理,要求目标类必须能够被继承,即不能是final的类。
       CGLIB经常被应用在框架中,例如spring,hibernate等。cglib的代理效果高于jdk。项目中直接使用动态代理的地方不多。一般都使用框架提供的功能。

总结:第三方的工具库,创建代理对象,原理是继承。通过继承目标类,创建子类。子类就是代理对象。要求目标类不能是final的,方法也不能是final的。

4.动态代理的作用
  • 1)在目标类源代码不改变的情况下,增加功能。
  • 2)减少代码的重复
  • 3)专注业务逻辑代码
  • 4)解耦合,让你的业务功能和日志,事务非业务功能分离。
5.jdk动态代理实现步骤

动态代理:可以在程序的执行过程中,创建代理对象。
通过代理对象执行方法,给目标类的方法增加额外的功能(功能增强)

  • 1.创建目标类,SomeServiceImpl目标类,给它的doSome,doOther增加 输出时间,事务。
package com.putao.service;

public interface SomeService {

    void doSome();
    void doOther();
}
package com.putao.service.impl;

import com.putao.service.SomeService;
import com.putao.util.ServiceTools;

import java.util.Date;

//service类的代码不修改,也能增加 输出时间,事务。
public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome() {
        System.out.println("执行业务方法doSome");
        int res = 10 + 20;
        //更新购买商品的库存,生成订单,结算整个购买商品的总价
    }

    @Override
    public void doOther() {
        System.out.println("执行业务方法doOther");
    }
}
  • 2.创建InvocationHandler接口的实现类,在这个类中实现给目标方法增加功能。
    ServiceTools工具类
package com.putao.util;

import java.util.Date;

public class ServiceTools {

    public static void doLog(){
        System.out.println("非业务方法,方法的执行时间:"+new Date());
    }

    public static void doTrans(){
        //方法的最后,提交事务
        System.out.println("非业务方法,方法执行完毕后,提交事务");
    }
}

实现类

package com.putao.handler;

import com.putao.util.ServiceTools;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {

    private Object target; //SomeServiceImpl

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //通过代理对象执行方法时,会调用执行这个invoke()
        System.out.println("执行MyInvocationHandler中的invoke");
        System.out.println("method名称:"+method.getName());
        String methodName = method.getName();
        Object res = null;

        if ("doSome".equals(methodName)){//JoinPoint  PointCut
            ServiceTools.doLog();//在目标方法之前,输出时间
            //执行目标类的方法,通过Method类实现
            res = method.invoke(target,args); //SomeServiceImpl.doSome()

            ServiceTools.doTrans();//在目标方法执行之后,提交事物
        }else {
            res = method.invoke(target,args); //SomeServiceImpl.doOther()
        }
        //目标方法执行结果
        return res;
    }
}

  • 3.使用jdk中的类Proxy,创建代理对象。实现创建对象的能力。
package com.putao;

import com.putao.handler.MyInvocationHandler;
import com.putao.service.SomeService;
import com.putao.service.impl.SomeServiceImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class MyApp {

    public static void main(String[] args) {
        //调用doSome,doOther
//        SomeService service = new SomeServiceImpl();
//        service.doSome();
//        System.out.println("================");
//        service.doOther();

        //使用jdk的Proxy创建代理对象
        //创建目标对象
        SomeService target = new SomeServiceImpl();

        //创建InvocationHandler对象
        InvocationHandler handler = new MyInvocationHandler(target);

        //创建代理
        SomeService proxy = (SomeService) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),handler);
        //com.sun.proxy.$Proxy0
        System.out.println("proxy===="+proxy.getClass().getName());
        //通过代理执行方法,会调用handler中的invoke()
        proxy.doSome();
        System.out.println("==================");
        proxy.doOther();
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/284586.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号