Java入坑之代理

一、代理模式和静态代理

1.1代理模式

代理模式

  • Proxy Pattern, 23个经典模式的一种,又称委托模式

-为目标对象提供(包装)了一个代理,这个代理可以控制对目标对象的访问

  • 外界不用直接访问目标对象,而是访问代理对象,由代理对象再调用目标对象
  • 代理对象中可以添加监控和审查处理
  • David Wheeler(函数的发明者):All problems in computer science can be solved by another level of indirection。

1.2静态代理

1.3静态代理代码演示

java 复制代码
package org.example;

public interface Subject{
    public void request();
}
java 复制代码
package org.example;

//目标对象
class SubjectImpl implements Subject {
    public void request() {
        System.out.println("I am dealing the request.");
    }
}
java 复制代码
package org.example;

//代理对象
class StaticProxy implements Subject{
    //实际目标对象
    private Subject subject;
    public StaticProxy(Subject subject){
        this.subject = subject;
    }
    public void request(){
        System.out.println("PreProcess");
        subject.request();
        System.out.println("PostProcess");
    }
}
java 复制代码
package org.example;

//静态代理模式
public class StaticProxyDemo {
    public static void main(String args[]) {
//创建实际对象
        SubjectImpl subject = new SubjectImpl();
//把实际对象封装到代理对象中
        StaticProxy p = new StaticProxy(subject);
        p.request();
    }
}

二、动态代理

2.1代理处理器

-持有目标对象的句柄

  • 实现InvocationHandler接口
  • 实现invoke方法
  • 所有的代理对象方法调用,都会转发到invoke方法来
  • invoke的形参method,就是指代理对象方法的调用
  • 在invoke内部,可以根据method,使用目标对象不同的方法来响应请求

2.2代码示例

java 复制代码
package org.example;

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

// 创建一个接口,将会被代理
interface Calculator {
    int add(int a, int b);
}

// 创建一个实现了 InvocationHandler 接口的代理处理器类
class CalculatorInvocationHandler implements InvocationHandler {
    private Object target; // 被代理的对象

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

    // 实现 invoke 方法,用于处理代理对象上的方法调用
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在调用被代理对象的方法之前可以执行一些逻辑
        System.out.println("Before invoking " + method.getName());

        // 使用 Java 反射调用被代理对象上的方法
        Object result = method.invoke(target, args);

        // 在调用被代理对象的方法之后可以执行一些逻辑
        System.out.println("After invoking " + method.getName());

        return result; // 返回方法的结果
    }
}

public class DynamicProxyHandlerExample {
    public static void main(String[] args) {
        // 创建被代理的对象
        Calculator realCalculator = new Calculator() {
            public int add(int a, int b) {
                return a + b;
            }
        };

        // 创建代理处理器对象
        CalculatorInvocationHandler handler = new CalculatorInvocationHandler(realCalculator);

        // 使用 Proxy 类生成代理对象
        Calculator proxy = (Calculator) Proxy.newProxyInstance(
                Calculator.class.getClassLoader(),
                new Class[]{Calculator.class},
                handler
        );

        // 调用代理对象的方法
        int result = proxy.add(5, 3);
        System.out.println("Result: " + result);
    }
}

2.3代理对象

三、AOP编程

AOP编程是一种软件开发技术,它可以将横切关注点(cross-cutting concerns)从业务逻辑中分离出来,实现代码的模块化和复用。横切关注点是指那些影响了多个类或方法的功能,例如日志、安全、事务等。AOP通过在运行时或编译时动态地将切面(aspect)织入到目标对象中,来增强目标对象的功能。切面是由通知(advice)和切点(pointcut)组成的,通知定义了切面要做什么,切点定义了切面要在哪里做。

3.1优点

  • 可以提高代码的可读性和可维护性,因为横切关注点被集中在一个地方,而不是分散在多个类或方法中。
  • 可以提高代码的复用性和扩展性,因为横切关注点可以被重用和修改,而不影响业务逻辑的核心功能。
  • 可以提高代码的稳定性和安全性,因为横切关注点可以对业务逻辑进行统一的处理,例如异常处理、事务管理等。

3.2常见应用场景

  • 日志记录:可以在方法的执行前后记录日志,方便调试和监控。
  • 权限检查:可以在方法的执行前检查用户的权限,防止非法访问。
  • 缓存管理:可以在方法的执行后将结果缓存起来,提高性能。
  • 性能统计:可以在方法的执行前后统计执行时间,优化性能。
  • 事务管理:可以在方法的执行前后进行事务的开启和提交,保证数据的一致性

3.3哪些框架使用了AOP

AOP是一种软件开发技术,它可以将横切关注点(cross-cutting concerns)从业务逻辑中分离出来,实现代码的模块化和复用。在Java中,有很多框架使用了AOP,例如:

  • Spring Framework:Spring Framework是一个提供了全面的编程和配置模型的Java企业级应用开发框架1。Spring Framework支持AOP,可以让开发者通过注解或XML配置的方式,定义切面(aspect)和切点(pointcut),并将它们织入到目标对象中,实现功能的增强2。Spring Framework的AOP模块主要基于动态代理(dynamic proxy)技术,也可以使用AspectJ编译器来实现静态织入(static weaving)。
  • AspectJ:AspectJ是一个基于Java语言的AOP框架,它扩展了Java语法,引入了新的关键字和语法结构,让开发者可以直接在源代码中定义切面和切点,并通过AspectJ编译器将它们编译成字节码。AspectJ提供了更强大和灵活的AOP功能,可以支持更多种类的切点和通知(advice),例如构造器调用、字段读写、异常处理等。
  • Guice:Guice是一个轻量级的依赖注入(dependency injection)框架,它可以让开发者通过注解的方式,声明对象之间的依赖关系,并自动创建和管理对象的生命周期。Guice也支持AOP,可以让开发者通过@Interceptor注解,定义方法拦截器(method interceptor),并将它们绑定到指定的切点上,实现功能的增强。Guice的AOP模块基于动态代理技术,只能拦截接口方法或非final类方法。

3.4面向切面与面向对象的区别

相关推荐
上等猿7 分钟前
集合stream
java
java1234_小锋11 分钟前
MyBatis如何处理延迟加载?
java·开发语言
菠萝咕噜肉i12 分钟前
MyBatis是什么?为什么有全自动ORM框架还是MyBatis比较受欢迎?
java·mybatis·框架·半自动
林的快手27 分钟前
209.长度最小的子数组
java·数据结构·数据库·python·算法·leetcode
FeboReigns29 分钟前
C++简明教程(10)(初识类)
c语言·开发语言·c++
学前端的小朱30 分钟前
处理字体图标、js、html及其他资源
开发语言·javascript·webpack·html·打包工具
向阳12181 小时前
mybatis 缓存
java·缓存·mybatis
上等猿1 小时前
函数式编程&Lambda表达式
java
摇光931 小时前
js高阶-async与事件循环
开发语言·javascript·事件循环·宏任务·微任务
沐泽Mu1 小时前
嵌入式学习-QT-Day09
开发语言·qt·学习