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

Java之代理模式静态代理与动态代理简单理解

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

Java之代理模式静态代理与动态代理简单理解

        众所周知代理模式很是常用的,比如Spring、SpringAOP等,这些的底层都使用到了代理模式,代理模式又分为静态代理、动态代理,但如何理解代理模式呢?下方以代码进行实现:

目录

静态代理:

动态代理:

结论


静态代理:

首先为静态代理,为什么叫静态?因为它是事先预定好的(已经创建好的),下方代码演示:

先创建两个目标接口:

UserMySQLDao:

public interface UserMySQLDao {

    void addMySQLData();

    void deleteMySQLData();

    void updateMySQLData();

    void selectMySQLData();

}

UserOracleDao: 

public interface UserOracleDao {

    void addOracleData();

    void deleteOracleData();

    void updateOracleData();

    void selectOracleData();

}

再次创建两个目标对象并且实现它们:

 UserMySQLDaoImpl:

public class UserMySQLDaoImpl implements UserMySQLDao {

    @Override
    public void addMySQLData() {
        System.out.println("MySQL add 1 row true!");
    }

    @Override
    public void deleteMySQLData() {
        System.out.println("MySQL delete 1 row true!");
    }

    @Override
    public void updateMySQLData() {
        System.out.println("MySQL update 1 row true!");
    }

    @Override
    public void selectMySQLData() {
        System.out.println("MySQL select 1 row true!");
    }
}

 UserOracleDaoImpl:

public class UserOracleDaoImpl implements UserOracleDao {
    @Override
    public void addOracleData() {
        System.out.println("Oracle add 1 row true!");
    }

    @Override
    public void deleteOracleData() {
        System.out.println("Oracle delete 1 row true!");
    }

    @Override
    public void updateOracleData() {
        System.out.println("Oracle update 1 row true!");
    }

    @Override
    public void selectOracleData() {
        System.out.println("Oracle select 1 row true!");
    }
}

现在已经将目标接口与目标对象创建完成,并且目标对象已经实现了目标接口,我们来创建两个代理对象:

ProxyMySQLObject:

public class ProxyMySQLObject implements UserMySQLDao {

    private UserMySQLDao userMySQLDao;

    public ProxyMySQLObject(UserMySQLDao userMySQLDao) {
        this.userMySQLDao = userMySQLDao;
    }

    @Override
    public void addMySQLData() {
        System.out.println("[Debug]:向 MySQL 数据库中添加一条数据...");
        userMySQLDao.addMySQLData();
    }

    @Override
    public void deleteMySQLData() {
        System.out.println("[Debug]:向 MySQL 数据库中删除一条数据...");
        userMySQLDao.deleteMySQLData();
    }

    @Override
    public void updateMySQLData() {
        System.out.println("[Debug]:向 MySQL 数据库中修改一条数据...");
        userMySQLDao.updateMySQLData();
    }

    @Override
    public void selectMySQLData() {
        System.out.println("[Debug]:向 MySQL 数据库中查询一条数据...");
        userMySQLDao.selectMySQLData();
    }
}

ProxyOracleObject: 

public class ProxyOracleObject implements UserOracleDao {

    private UserOracleDao userOracleDao;

    public ProxyOracleObject(UserOracleDao userOracleDao) {
        this.userOracleDao = userOracleDao;
    }

    @Override
    public void addOracleData() {
        System.out.println("[Debug]:向 Oracle 数据库中添加一条数据...");
        userOracleDao.addOracleData();
    }

    @Override
    public void deleteOracleData() {
        System.out.println("[Debug]:向 Oracle 数据库中删除一条数据...");
        userOracleDao.deleteOracleData();
    }

    @Override
    public void updateOracleData() {
        System.out.println("[Debug]:向 Oracle 数据库中修改一条数据...");
        userOracleDao.updateOracleData();
    }

    @Override
    public void selectOracleData() {
        System.out.println("[Debug]:向 Oracle 数据库查询一条数据...");
        userOracleDao.selectOracleData();
    }
}

在不改变目标接口的情况下进行功能迭代,我这边就以添加一个输出语句为例,我们进行测试:

    //静态代理测试:操作Oracle的代理对象,静态代理:目标对象与代理对象都需要实现一样的接口。
    public static void testProxyStaticOracle(){
        ProxyOracleObject proxyOracleObject = new ProxyOracleObject(new UserOracleDaoImpl());
        proxyOracleObject.addOracleData();
        proxyOracleObject.deleteOracleData();
        proxyOracleObject.selectOracleData();
        proxyOracleObject.updateOracleData();
    }

    //静态代理测试:操作 MySQL 的代理对象,静态代理:目标对象与代理对象都需要实现一样的接口。
    public static void testProxyStaticMySQL(){
        ProxyMySQLObject proxyMySQLObject = new ProxyMySQLObject(new UserMySQLDaoImpl());
        proxyMySQLObject.addMySQLData();
        proxyMySQLObject.deleteMySQLData();
        proxyMySQLObject.selectMySQLData();
        proxyMySQLObject.updateMySQLData();
    }

通过以上静态代理代码,由此可以发现:

        静态代理可以在不改变目标对象的情况下进行功能迭代。但是随着业务的需要,当目标对象的新增,那么代理对象也需要新增,并且目标对象与代理对象都需要实现共同的一个接口,也就是后期维护较繁琐化。

动态代理:

        我们再来看动态代理,动态代理与静态代理的区别就是动态代理是动态的在内存中创建代理对象,而不需要手动硬编码代理对象。

动态代理示例,我们以JDK代理为例,目标对象不变,我们创建一个代理处理器并且实现JDK自带的处理器InvocationHandler :

ProxyDynamicHandler:

public class ProxyDynamicHandler implements InvocationHandler {

    private Object object;

    public ProxyDynamicHandler(Object object) { //简易的修饰者模式动态创建对象
        this.object = object;
    }

    //获取在内存创建的代理对象
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object invoke = method.invoke(object, args);
        if(invoke != null){
            return invoke;
        }
        return null;
    }
}

测试:

    public static void testProxt(){
        //动态代理 代理 MySQL 目标对象
        ProxyDynamicHandler proxyDynamicInvocationMySQLHandler = new ProxyDynamicHandler(new UserMySQLDaoImpl());
        UserMySQLDao  userMySQLDao = (UserMySQLDao) proxyDynamicInvocationMySQLHandler.getProxy();
        System.out.println("向 MySQL 数据库查询数据");
        userMySQLDao.selectMySQLData(); //这里拿到接口后,一样可以不改变源接口的基础下进行功能迭代,还是以输出语句为例,当然拿到接口后你想怎么操作就怎么操作

        System.out.println("============分割线:下方为 代理 Oracle 目标对象");

        //动态代理 代理 Oracle 目标对象
        ProxyDynamicHandler proxyDynamicInvocationOracleHandler = new ProxyDynamicHandler(new UserOracleDaoImpl());
        UserOracleDao userOracleDao = (UserOracleDao) proxyDynamicInvocationOracleHandler.getProxy();
        System.out.println("向 Oracle 数据库中修改了一条数据!");
        userOracleDao.updateOracleData();
    }

运行结果:

向 MySQL 数据库查询数据
MySQL select 1 row true!
============分割线:下方为 代理 Oracle 目标对象
向 Oracle 数据库中修改了一条数据!
Oracle update 1 row true!

通过动态代理模式,得出结论:

        动态代理不需要创建多个代理对象,它是动态的在内存中创建代理对象,动态代理同样可以保证不改变源代码的情况下进行功能迭代,并且维护对比静态代理更加方便、灵活。

结论

动态代理与静态代理的区别:

        静态与动态代理都可以不改变源代码的情况下进行功能迭代

        静态代理是需要 目标对象 与 代理对象实现同一个接口,如果随着业务的增多,代理对象也会增多,后期维护不方便,繁琐化,而且代理对象是事先创建好的,硬编码在程序中。

        动态代理则是动态的在内存中创建代理对象,没有硬编码在程序中,使用起来更加方便、灵活,后期维护相比静态代理更加简单

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

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

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