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

AOP先篇:动态代理

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

AOP先篇:动态代理

AOP先篇:动态代理

在介绍AOP之前,先给大家介绍一下动态代理的知识

先来给大家举个简单的例子,现在有如下用户接口和其实现类(为方便起见,实现类中只打印对应语句)

package com.zy.service;

public interface userService
{
    public void selectUser();

    public void insertUser();
}
package com.zy.service;

public class userServiceImpl implements userService
{

    @Override
    public void selectUser()
    {
        System.out.println("查找用户");
    }

    @Override
    public void insertUser()
    {
        System.out.println("插入用户");
    }
}

现在要给这两个方法添加两个功能: 在执行前 添加记录时间功能 在执行后添加 **记录日志**功能,我们要如何实现呢?

方式1:

大多数人可能会想,直接在两个方法中都添加 这两个新功能 即可,如下所示

public class userServiceImpl implements userService
{

    @Override
    public void selectUser()
    {
        System.out.println("执行时间为:" + new Date());
        System.out.println("查找用户");
        System.out.println("打印日志信息");
    }

    @Override
    public void insertUser()
    {
        System.out.println("执行时间为:" + new Date());
        System.out.println("插入用户");
        System.out.println("打印日志信息");
    }
}

但是这样就改变了原有代码,并且原本处理业务的代码与新添加的无关业务代码就融合在了一起,并且大量重复,这就导致了方法很杂乱,而且如果我们修改无关业务的代码就要在每个函数中都进行修改,那我们应该怎么优化呢?

方式2:

我们将无关业务的代码单独提取出来,封装到一个工具类,并在业务代码中调用即可,如下所示

public class otherService
{
    public static void getTime()
    {
        System.out.println("执行时间为:" + new Date());
    }

    public static void getLog()
    {
        System.out.println("打印日志信息");
    }
}
@Override
public void selectUser()
{
    otherService.getTime();
    System.out.println("查找用户");
    otherService.getLog();
}

@Override
public void insertUser()
{
    otherService.getTime();
    System.out.println("插入用户");
    otherService.getLog();
}

这样解决了部分问题,但是我们还可以发现,业务类代码中还是调用者非业务代码,耦合性还是太高,这就引出了我们的动态代理~

动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类。代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架。

基本过程如下所示,由代理类通过业务接口创建代理类对象,最后返回代理类对象。

方式3:

我们接着用JDK自带的动态代理的方式,解决上述需求

首先我们创建UserService代理类 实现InvocationHandler接口

package com.zy.service;

public class UserProxy implements InvocationHandler
{
    private Object target;//代理接口(目标对象)

    public UserProxy(Object target)
    {
        this.target = target;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    {
        otherService.getTime();//打印时间
        Object invoke = method.invoke(target, args);
        otherService.getLog();//打印日志
        return invoke;
    }
    
     public void setTarget(Object target)
    {
        this.target = target;
    }
}

接着为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类

public void test()
{
    //首先创建目标对象
    UserServiceImpl target = new UserServiceImpl();
    //创建InvocationHandler对象
    UserProxy proxy = new UserProxy(target);
    //使用Proxy创建代理
    UserService userService = (UserService) Proxy.newProxyInstance(target.getClass().getClassLoader(),
            target.getClass().getInterfaces(), proxy);

    //测试代理类对象
    userService.insertUser();
}

结果如下

这样的话,我们没有修改原有的业务代码却达成了添加新功能的作用。

动态代理作用

通过上面的例子,我们可以发现动态代理有以下作用

  • 可以在目标类源代码不改变的情况下,增加功能。
  • 可以减少代码的重复。
  • 可以使程序员专注业务逻辑代码。
  • 可以使代码解耦合,让的业务功能与非业务功能分离。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/282612.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

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

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