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面向切面与面向对象的区别

相关推荐
爱吃生蚝的于勒42 分钟前
C语言内存函数
c语言·开发语言·数据结构·c++·学习·算法
码上一元2 小时前
SpringBoot自动装配原理解析
java·spring boot·后端
计算机-秋大田2 小时前
基于微信小程序的养老院管理系统的设计与实现,LW+源码+讲解
java·spring boot·微信小程序·小程序·vue
小白学大数据3 小时前
Python爬虫开发中的分析与方案制定
开发语言·c++·爬虫·python
魔道不误砍柴功4 小时前
简单叙述 Spring Boot 启动过程
java·数据库·spring boot
冰芒猓4 小时前
SpringMVC数据校验、数据格式化处理、国际化设置
开发语言·maven
失落的香蕉4 小时前
C语言串讲-2之指针和结构体
java·c语言·开发语言
枫叶_v4 小时前
【SpringBoot】22 Txt、Csv文件的读取和写入
java·spring boot·后端
wclass-zhengge4 小时前
SpringCloud篇(配置中心 - Nacos)
java·spring·spring cloud
路在脚下@4 小时前
Springboot 的Servlet Web 应用、响应式 Web 应用(Reactive)以及非 Web 应用(None)的特点和适用场景
java·spring boot·servlet