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

JDK动态代理实现和原理分析

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

JDK动态代理实现和原理分析

动态代理的作用:目标方法代码不修改,为其添加功能。

动态代理底层涉及知识点:反射,类加载器,可以参考博客反射、类对象和类加载器_source code August的博客-CSDN博客

前言

Spring的AOP,可以理解为动态代理实现的一种规范化,因为我们自己实现动态代理可以使用JDK动态代理,也可以使用CGLIB动态代理。这两种都是Spring AOP的底层实现原理,使用场景:

若目标对象实现了接口,spring默认使用JDK的动态代理。

优点:因为有接口,所以使系统更加松耦合

缺点:为每一个目标类创建接口

若目标对象没有实现任何接口,spring使用CGLIB进行动态代理。

优点:因为代理类与目标类是继承关系,所以不需要有接口的存在。

缺点:因为没有使用接口,所以系统的耦合性没有使用JDK的动态代理好。

若目标对象实现了接口,但是强制cglib代理,则使用cglib代理

JDk动态代理的代码实现

1.目标对象SomeService。(JDK动态代理要求目标对象必须实现接口)

2.InvocationHandler接口实现

3.测试类

4.输出结果

5.原理分析

1.目标对象SomeService
//定义目标接口
public interface SomeService {
    public void doSome();
    public void doOther();
}
//定义目标实现类
public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome() {
        System.out.println("doSome");
    }
    @Override
    public void doOther() {
        System.out.println("domeOther");
    }
}
2.InvocationHandler接口实现
public class MyInvocationHandler implements InvocationHandler {
    //动态代理的目标对象
    private Object target;
    //构造方法,在new InvocationHandler的时候传入目标类对象
    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //通过代理对象执行方法时,会调用执行这个invoke()
        Object res=null;
        //如果代理类对象执行的是doSome才进行功能增强。
        if (method.getName().equals("doSome")){
            System.out.println("在doSome之前执行");
            //执行目标类的方法,通过method类执行invoke方法实现
            res=method.invoke(target,args);
            System.out.println("在doSome之后执行");
        }else {
            res=method.invoke(target,args);
        }
        return res;
    }
}
3.测试类
public class Test {
    public static void main(String[] args) {
        SomeService someService = new SomeServiceImpl();
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(someService);
        //使用proxy创建代理,newProxyInstance是静态方法,可以直接"类名.方法"使用,第二个参数是获取有哪些接口方法
        Object o = Proxy.newProxyInstance(someService.getClass().getClassLoader(), someService.getClass().getInterfaces(), myInvocationHandler);
        //上面Object可以使用强转,为SomeService
        SomeService proxy=(SomeService) o;
        //通过代理执行方法,会调用handler中的invoke()
        proxy.doSome();//调用doSome方法
    }
}
4.输出结果

测试类执行doSome 

测试类执行doOther

通过代理,实现了在不修改目标类方法代码的情况下,通过代理执行目标类方法,在目标类方法执行的时候,为其增加了功能。比如这里的"在domeSome之前执行" 和“在domeSome之后执行”就是增加的功能。这些增加的代码,就是我们常说的"切面"。

关于详细的Spring AOP使用可以参考博客“https://正在连载”

5.原理分析

动态代理底层涉及知识点:反射,类加载器,可以参考博客反射、类对象和类加载器_source code August的博客-CSDN博客

为什么JDK动态代理要求目标对象必须实现接口?可以发现前面创建的代理类对象进行了强制类型转换,SomeService proxy=(SomeService) o;代理对象需要强制类型转化为目标类才可以调用目标类的方法。关于强制类型转化的理解可以参考:Java强制类型转化和自动类型转化_source code August的博客-CSDN博客

连载中...

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

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

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