Java代理模式——静态代理与动态代理

简介: Java代理模式——静态代理与动态代理

代理模式

代理模式允许你为其他对象提供一个代理,以控制对这个对象的访问。代理模式在不改变实际对象的情况下,可以在访问对象时添加额外的功能。

可以理解为代理模式为被代理对象创造了一个替身,调用者可以通过这个替身去实现这个被代理对象的功能,这个替身也可以为被代理对象增加功能

静态代理

定义

使用时候需要定义接口或者父类。 代理类和委托类有共同的父类或父接口。

案例

首先定义一个接口 ITeacherDao,并在这个接口中定义一个teacher()方法。

package Static;
 
public interface ITeacherDao {
    void teacher();
}

再写一个他的实现类,实现teacher()方法

package Static;
 
public class TeacherDao implements ITeacherDao{
    @Override
    public void teacher() {
        System.out.println("老师在教课");
    }
}

如上,我们实现了一个简单接口与他的实现类,接下来我们实现一个老师的静态代理类

package Static;
 
public class TeacherDaoProxy implements ITeacherDao{
 
    private TeacherDao teacherDao;
 
    public TeacherDaoProxy(TeacherDao teacherDao){
        this.teacherDao = teacherDao;
    }
    @Override
    public void teacher() {
        System.out.println("代理前");
        teacherDao.teacher();
        System.out.println("代理后");
    }
}

在这段代码中,我们实现了TeacherDao的代理类,并通过调用teacherDao这个对象使用了被代理对象的方法;我们在使用被代理对象方法前后都拓展了新的功能,这就是静态代理。

下面是主函数对于静态代理的使用

public class Main {
    public static void main(String[] args) {
        Static.TeacherDao teacherDao = new TeacherDao();
 
        TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);
 
        teacherDaoProxy.teacher();
    }
}

这说明我们的代理类在实现被代理对象的功能时也拓展了新的功能

但是,这样的模式也存在一种缺陷,就是我们的代理对象和被调用对象都要实现同一接口或父类,可能会出现多个代理类,接口如果要增加方法的话会有很多代理类需要维护;针对这一问题,Java的开发者定义了相关方法去解决,这就是我们下面要介绍的被代理类。

动态代理

定义

不需要实现接口,但是被代理的目标对象需要实现,调用jdk的api形成代理对象,

动态代理就是通过使用反射,动态地获取抽象接口的类型,从而获取相关特性进行代理。

案例

我们还是先定义一个接口

public interface ITeacherDao {
    void teacher();
    void sayhello();
}

接着我们定义他的实现类

public class TeacherDao implements ITeacherDao {
    @Override
    public void teacher() {
        System.out.println("老师在教课");
    }
 
    @Override
    public void sayhello() {
        System.out.println("hello");
    }
}

接着我们实现一个动态的代理类,可以动态代理原对象;在这个代理类中,我们使用到了Proxy.newProxyInstance 这个函数,他有三个参数,以下是三个参数的解释

1.target.getClass().getClassLoader():获取被代理对象的类加载器。这是用于加载代理类的类加载器。

2.target.getClass().getInterfaces():获取被代理对象实现的接口。这些接口是代理类将要实现的接口。

3.new InvocationHandler() { ... }:创建一个匿名的 InvocationHandler 对象,它实现了 invoke 方法,这是代理逻辑的核心部分。

我们在InvocationHandler() { ... }中调用了被代理对象的方法,并且做了一些扩展

public class FactoryProxy  {
    private Object target;
 
    public FactoryProxy(Object target){
        this.target = target;
    }
 
    public Object getProxyIstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("代理前");
                Object returnVal = method.invoke(target,args);
                System.out.println("代理后");
 
                return returnVal;
            }
        });
    };
}

在主函数中调用被代理类,创建一个接口类,讲接口类传入被代理类,然后就可以定义接口类中的方法了,即实现了动态代理。

public class Main {
    public static void main(String[] args) {
        ITeacherDao iteacherDao = new TeacherDao();
 
        ITeacherDao proxyInstance = (ITeacherDao) new FactoryProxy(iteacherDao).getProxyIstance();
 
        proxyInstance.teacher();
        proxyInstance.sayhello();
 
    }
}

最终输出结果

可以看出,我们通过动态代理类实现了对目标对象的功能拓展

链接

java静态代理与动态代理: java静态代理与动态代理

目录
相关文章
|
1月前
|
Java
JAVA 静态代理 & 动态代理
【11月更文挑战第14天】静态代理是一种简单的代理模式实现,其中代理类和被代理类的关系在编译时已确定。代理类实现与被代理类相同的接口,并持有被代理类的实例,通过调用其方法实现功能增强。优点包括代码结构清晰,易于理解和实现;缺点是对于多个被代理类,需为每个类编写相应的代理类,导致代码量大增,维护成本高。动态代理则在运行时动态生成代理类,更加灵活,减少了代码冗余,但可能引入性能损耗和兼容性问题。
|
2月前
|
设计模式 Java API
[Java]静态代理与动态代理(基于JDK1.8)
本文介绍了代理模式及其分类,包括静态代理和动态代理。静态代理分为面向接口和面向继承两种形式,分别通过手动创建代理类实现;动态代理则利用反射技术,在运行时动态创建代理对象,分为JDK动态代理和Cglib动态代理。文中通过具体代码示例详细讲解了各种代理模式的实现方式和应用场景。
33 0
[Java]静态代理与动态代理(基于JDK1.8)
|
2月前
|
Java
Java访问外网图片地址时,如何添加代理?
【10月更文挑战第14天】Java访问外网图片地址时,如何添加代理?
45 2
|
2月前
|
Java
Java代码解释静态代理和动态代理的区别
### 静态代理与动态代理简介 **静态代理**:代理类在编译时已确定,目标对象和代理对象都实现同一接口。代理类包含对目标对象的引用,并在调用方法时添加额外操作。 **动态代理**:利用Java反射机制在运行时生成代理类,更加灵活。通过`Proxy`类和`InvocationHandler`接口实现,无需提前知道接口的具体实现细节。 示例代码展示了两种代理方式的实现,静态代理需要手动创建代理对象,而动态代理通过反射机制自动创建。
|
2月前
|
设计模式 缓存 Java
从源码学习Java动态代理|8月更文挑战
从源码学习Java动态代理|8月更文挑战
|
7天前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
37 6
|
22天前
|
设计模式 Java 开发者
Java多线程编程的陷阱与解决方案####
本文深入探讨了Java多线程编程中常见的问题及其解决策略。通过分析竞态条件、死锁、活锁等典型场景,并结合代码示例和实用技巧,帮助开发者有效避免这些陷阱,提升并发程序的稳定性和性能。 ####
|
20天前
|
存储 监控 小程序
Java中的线程池优化实践####
本文深入探讨了Java中线程池的工作原理,分析了常见的线程池类型及其适用场景,并通过实际案例展示了如何根据应用需求进行线程池的优化配置。文章首先介绍了线程池的基本概念和核心参数,随后详细阐述了几种常见的线程池实现(如FixedThreadPool、CachedThreadPool、ScheduledThreadPool等)的特点及使用场景。接着,通过一个电商系统订单处理的实际案例,分析了线程池参数设置不当导致的性能问题,并提出了相应的优化策略。最终,总结了线程池优化的最佳实践,旨在帮助开发者更好地利用Java线程池提升应用性能和稳定性。 ####
|
22天前
|
缓存 Java 开发者
Java多线程编程的陷阱与最佳实践####
本文深入探讨了Java多线程编程中常见的陷阱,如竞态条件、死锁和内存一致性错误,并提供了实用的避免策略。通过分析典型错误案例,本文旨在帮助开发者更好地理解和掌握多线程环境下的编程技巧,从而提升并发程序的稳定性和性能。 ####
下一篇
DataWorks