当前位置: 首页 > news >正文

PHP 中 Class 的使用说明

文章目录

  • PHP 中 Class 的使用说明
    • 1. 类(Class)的基础概念
    • 2. 类的定义与实例化
      • 2.1 定义类
      • 2.2 实例化类(创建对象)
      • 2.3 构造函数
      • 2.4 析构函数
    • 3. 属性(Properties)
      • 3.1 属性的类型
      • 3.2 属性的访问控制
      • 3.3 属性的默认值
      • 3.4 静态属性
      • 3.5 只读属性(PHP 8.1+)
    • 4. 方法(Methods)
      • 4.1 方法的定义和调用
      • 4.2 方法的访问控制
      • 4.3 静态方法
      • 4.4 抽象方法
      • 4.5 魔术方法
    • 5. 继承(Inheritance)
      • 5.1 基本继承
      • 5.2 调用父类的方法
      • 5.3 多继承的替代方案(Trait)
    • 6. 多态(Polymorphism)
    • 7. 抽象类与接口
      • 7.1 抽象类
      • 7.2 接口
      • 7.3 抽象类与接口的区别
    • 8. 面向对象设计原则
      • 8.1 单一职责原则(SRP)
      • 8.2 开闭原则(OCP)
      • 8.3 里氏替换原则(LSP)
      • 8.4 接口隔离原则(ISP)
      • 8.5 依赖倒置原则(DIP)
    • 9. 高级类特性
      • 9.1 类的自动加载
      • 9.2 命名空间
      • 9.3 反射
      • 9.4 对象序列化
    • 10. 实际应用示例
      • 10.1 基础的 MVC 结构
      • 10.2 单例模式
      • 10.3 工厂模式
    • 11. 类的最佳实践
      • 11.1 命名规范
      • 11.2 代码组织
      • 11.3 可维护性
      • 11.4 安全性
    • 12. 总结

PHP 中 Class 的使用说明

1. 类(Class)的基础概念

在 PHP 中,类是面向对象编程(OOP)的核心概念,它是一种用于创建对象的蓝图或模板。类定义了对象的属性(数据)和方法(行为),而对象则是类的实例化。

类的主要特性包括:

  • 封装:将数据和方法组合在一个单元中
  • 继承:允许一个类基于另一个类构建
  • 多态:允许不同的类实现相同的方法但有不同的行为
  • 抽象:允许定义接口和抽象类

2. 类的定义与实例化

2.1 定义类

使用 class 关键字定义一个类:

<?php
// 定义一个简单的 Person 类
class Person {// 属性(成员变量)public $name;public $age;// 方法(成员函数)public function sayHello() {echo "Hello, my name is {$this->name}.";}
}
?>

2.2 实例化类(创建对象)

使用 new 关键字创建类的实例:

<?php
// 创建 Person 类的实例
$person = new Person();// 访问对象的属性并赋值
$person->name = "张三";
$person->age = 30;// 调用对象的方法
$person->sayHello(); // 输出: Hello, my name is 张三.
?>

2.3 构造函数

构造函数是一种特殊的方法,在创建对象时自动调用,用于初始化对象的属性:

<?php
class Person {public $name;public $age;// 构造函数public function __construct($name, $age) {$this->name = $name;$this->age = $age;}public function sayHello() {echo "Hello, my name is {$this->name}.";}
}// 创建对象时直接传递参数
$person = new Person("张三", 30);
$person->sayHello(); // 输出: Hello, my name is 张三.
?>

2.4 析构函数

析构函数在对象被销毁时自动调用,通常用于清理资源:

<?php
class FileHandler {private $file;public function __construct($filename) {$this->file = fopen($filename, "r");}// 析构函数public function __destruct() {if ($this->file) {fclose($this->file);echo "文件已关闭";}}
}$handler = new FileHandler("example.txt");
// 当 $handler 不再被引用或脚本结束时,析构函数会自动调用
?>

3. 属性(Properties)

属性是类中用于存储数据的变量,也称为成员变量。

3.1 属性的类型

PHP 7.4+ 支持属性类型声明:

<?php
class Person {// 基本类型声明public string $name;public int $age;public float $height;public bool $isStudent;// 可为空类型(PHP 8.0+)public ?string $email;// 类类型声明public DateTime $registrationDate;
}
?>

3.2 属性的访问控制

PHP 提供了三种访问控制修饰符:

<?php
class Person {// 公共属性:可以在任何地方访问public $name;// 受保护属性:只能在类内部或子类中访问protected $email;// 私有属性:只能在定义它的类内部访问private $phone;// ...其他代码
}
?>

3.3 属性的默认值

可以为属性设置默认值:

<?php
class Person {public string $name = "Guest";public int $age = 0;public array $hobbies = [];public ?string $email = null;
}
?>

3.4 静态属性

静态属性属于类本身,而不是类的实例:

<?php
class Counter {// 静态属性public static int $count = 0;public function __construct() {self::$count++; // 使用 self:: 访问静态属性}
}$c1 = new Counter();
$c2 = new Counter();echo Counter::$count; // 输出: 2
?>

3.5 只读属性(PHP 8.1+)

只读属性只能在初始化时赋值一次:

<?php
class User {public readonly int $id;public function __construct(int $id) {$this->id = $id; // 只能在构造函数中赋值}
}$user = new User(123);
// $user->id = 456; // 错误:不能修改只读属性
?>

4. 方法(Methods)

方法是类中定义的函数,用于执行特定操作。

4.1 方法的定义和调用

<?php
class Calculator {// 方法定义public function add(int $a, int $b): int {return $a + $b;}
}$calc = new Calculator();
$result = $calc->add(5, 3); // 调用方法echo $result; // 输出: 8
?>

4.2 方法的访问控制

与属性一样,方法也有三种访问控制修饰符:

<?php
class Person {private $name;// 公共方法public function setName(string $name): void {$this->name = $name;}// 受保护方法protected function validateName(string $name): bool {return strlen($name) > 0;}// 私有方法private function formatName(string $name): string {return ucfirst($name);}
}
?>

4.3 静态方法

静态方法属于类本身,不依赖于类的实例:

<?php
class Math {// 静态方法public static function square(int $num): int {return $num * $num;}
}// 直接通过类名调用静态方法
$result = Math::square(5);
echo $result; // 输出: 25
?>

4.4 抽象方法

抽象方法是在抽象类中声明但不实现的方法,子类必须实现它:

<?php
abstract class Shape {// 抽象方法abstract public function calculateArea(): float;
}class Rectangle extends Shape {private $width;private $height;public function __construct(float $width, float $height) {$this->width = $width;$this->height = $height;}// 实现抽象方法public function calculateArea(): float {return $this->width * $this->height;}
}
?>

4.5 魔术方法

PHP 提供了一系列魔术方法,这些方法以双下划线 __ 开头,在特定情况下自动调用:

<?php
class Person {private $data = [];// 属性访问魔术方法public function __get($name) {return $this->data[$name] ?? null;}public function __set($name, $value) {$this->data[$name] = $value;}public function __isset($name) {return isset($this->data[$name]);}public function __unset($name) {unset($this->data[$name]);}// 方法调用魔术方法public function __call($name, $arguments) {echo "调用了方法 $name ,参数:" . implode(', ', $arguments);}// 静态方法调用魔术方法public static function __callStatic($name, $arguments) {echo "调用了静态方法 $name ,参数:" . implode(', ', $arguments);}// 字符串转换魔术方法public function __toString() {return "Person object";}
}
?>

5. 继承(Inheritance)

继承允许一个类(子类)基于另一个类(父类)构建,从而重用代码:

5.1 基本继承

<?php
// 父类
class Animal {protected $name;public function __construct($name) {$this->name = $name;}public function getName() {return $this->name;}public function makeSound() {echo "Some generic sound";}
}// 子类继承父类
class Dog extends Animal {// 重写父类的方法public function makeSound() {echo "Woof! Woof!";}// 子类特有的方法public function fetch() {echo "{$this->name} is fetching the ball";}
}// 创建子类的实例
$dog = new Dog("Rex");
echo $dog->getName(); // 输出: Rex
$dog->makeSound(); // 输出: Woof! Woof!
$dog->fetch(); // 输出: Rex is fetching the ball
?>

5.2 调用父类的方法

使用 parent:: 关键字调用父类的方法:

<?php
class ParentClass {public function sayHello() {echo "Hello from Parent";}
}class ChildClass extends ParentClass {public function sayHello() {// 调用父类的方法parent::sayHello();echo "Hello from Child";}
}$child = new ChildClass();
$child->sayHello(); // 输出: Hello from ParentHello from Child
?>

5.3 多继承的替代方案(Trait)

PHP 不支持多继承,但可以使用 Trait 实现类似功能:

<?php
// 定义一个 Traittrait Logger {public function log($message) {echo "[LOG] $message\n";}
}// 定义另一个 Traittrait Database {public function connect() {echo "Connected to database\n";}
}// 使用多个 Trait
class User {use Logger, Database;public function register() {$this->connect();$this->log("User registered");}
}$user = new User();
$user->register(); // 输出: Connected to database [LOG] User registered
?>

6. 多态(Polymorphism)

多态允许不同的类实现相同的接口或继承自同一个父类,但有不同的行为:

<?php
// 定义一个接口
interface Shape {public function calculateArea();
}// 实现接口的类
class Circle implements Shape {private $radius;public function __construct($radius) {$this->radius = $radius;}public function calculateArea() {return pi() * pow($this->radius, 2);}
}class Rectangle implements Shape {private $width;private $height;public function __construct($width, $height) {$this->width = $width;$this->height = $height;}public function calculateArea() {return $this->width * $this->height;}
}// 多态的使用
function printArea(Shape $shape) {echo "Area: " . $shape->calculateArea() . "\n";
}$circle = new Circle(5);
$rectangle = new Rectangle(4, 6);printArea($circle); // 输出: Area: 78.539816339745
printArea($rectangle); // 输出: Area: 24
?>

7. 抽象类与接口

7.1 抽象类

抽象类是不能直接实例化的类,可以包含抽象方法和普通方法:

<?php
// 定义抽象类
abstract class Vehicle {protected $brand;public function __construct($brand) {$this->brand = $brand;}// 普通方法public function getBrand() {return $this->brand;}// 抽象方法abstract public function startEngine();
}// 继承抽象类并实现抽象方法
class Car extends Vehicle {public function startEngine() {echo "{$this->brand} car engine started";}
}// 不能直接实例化抽象类
// $vehicle = new Vehicle("Toyota"); // 错误$car = new Car("Toyota");
$car->startEngine(); // 输出: Toyota car engine started
?>

7.2 接口

接口定义了一个类应该实现的方法,但不提供方法的具体实现:

<?php
// 定义接口
interface Logger {public function logInfo($message);public function logError($message);public function logWarning($message);
}// 实现接口
class FileLogger implements Logger {private $logFile;public function __construct($logFile) {$this->logFile = $logFile;}public function logInfo($message) {$this->writeLog("INFO", $message);}public function logError($message) {$this->writeLog("ERROR", $message);}public function logWarning($message) {$this->writeLog("WARNING", $message);}private function writeLog($level, $message) {$timestamp = date("Y-m-d H:i:s");$logEntry = "[$timestamp] [$level] $message\n";file_put_contents($this->logFile, $logEntry, FILE_APPEND);}
}// 使用实现了接口的类
$logger = new FileLogger("app.log");
$logger->logInfo("Application started");
$logger->logError("Database connection failed");
?>

7.3 抽象类与接口的区别

特性抽象类接口
方法实现可以包含已实现的方法只能包含方法声明,不能实现
属性可以包含各种访问级别的属性只能包含公共静态常量
继承一个类只能继承一个抽象类一个类可以实现多个接口
构造函数可以有构造函数不能有构造函数
访问控制可以使用各种访问修饰符方法默认为公共,不能使用其他修饰符

8. 面向对象设计原则

8.1 单一职责原则(SRP)

一个类应该只有一个责任:

<?php
// 好的设计:User 类只负责用户数据和行为
class User {private $id;private $name;private $email;// 只包含与用户相关的方法public function getName() { return $this->name; }public function setName($name) { $this->name = $name; }// ...
}// 好的设计:UserRepository 类只负责数据库操作
class UserRepository {public function save(User $user) { /* 保存用户到数据库 */ }public function findById($id) { /* 从数据库查找用户 */ }// ...
}
?>

8.2 开闭原则(OCP)

软件实体应该对扩展开放,对修改关闭:

<?php
// 好的设计:使用接口和继承实现开闭原则
interface PaymentMethod {public function pay($amount);
}class CreditCardPayment implements PaymentMethod {public function pay($amount) { /* 信用卡支付逻辑 */ }
}class PayPalPayment implements PaymentMethod {public function pay($amount) { /* PayPal支付逻辑 */ }
}// PaymentProcessor 对扩展开放,对修改关闭
class PaymentProcessor {public function processPayment(PaymentMethod $method, $amount) {return $method->pay($amount);}
}// 新增支付方式不需要修改 PaymentProcessor
class BitcoinPayment implements PaymentMethod {public function pay($amount) { /* 比特币支付逻辑 */ }
}
?>

8.3 里氏替换原则(LSP)

子类应该能够替换其父类:

<?php
class Rectangle {protected $width;protected $height;public function setWidth($width) { $this->width = $width; }public function setHeight($height) { $this->height = $height; }public function getArea() { return $this->width * $this->height; }
}// 正方形是一种特殊的矩形,但这个实现违反了里氏替换原则
class Square extends Rectangle {public function setWidth($width) {$this->width = $width;$this->height = $width;}public function setHeight($height) {$this->width = $height;$this->height = $height;}
}// 更好的设计:使用组合而非继承
interface Shape {public function getArea();
}class Rectangle implements Shape {// ...
}class Square implements Shape {// ...
}
?>

8.4 接口隔离原则(ISP)

不应该强迫客户端依赖于它们不使用的方法:

<?php
// 不好的设计:一个大而全的接口
interface Worker {public function work();public function eat();public function sleep();
}// 好的设计:将接口拆分为更小、更具体的接口
interface Workable {public function work();
}interface Eatable {public function eat();
}interface Sleepable {public function sleep();
}// 客户端可以只实现需要的接口
class HumanWorker implements Workable, Eatable, Sleepable {// 实现所有方法
}class RobotWorker implements Workable {// 只需要实现 work() 方法public function work() { /* 工作逻辑 */ }
}
?>

8.5 依赖倒置原则(DIP)

高层模块不应该依赖于低层模块,两者都应该依赖于抽象:

<?php
// 不好的设计:高层模块直接依赖低层模块
class UserService {private $mysqlRepository; // 直接依赖具体类public function __construct() {$this->mysqlRepository = new MySQLUserRepository();}
}// 好的设计:依赖于抽象接口
interface UserRepository {public function findById($id);public function save(User $user);
}class MySQLUserRepository implements UserRepository {// 实现接口方法
}class MongoDBUserRepository implements UserRepository {// 实现接口方法
}class UserService {private $repository; // 依赖于抽象接口// 通过构造函数注入依赖public function __construct(UserRepository $repository) {$this->repository = $repository;}
}
?>

9. 高级类特性

9.1 类的自动加载

使用 spl_autoload_register() 实现类的自动加载:

<?php
// 自动加载函数
function my_autoloader($class) {// 将命名空间分隔符转换为目录分隔符$path = str_replace('\\', DIRECTORY_SEPARATOR, $class);// 加载对应的类文件require_once __DIR__ . '/classes/' . $path . '.php';
}// 注册自动加载函数
spl_autoload_register('my_autoloader');// 现在可以直接使用类,不需要手动引入
$user = new App\Models\User();
?>

9.2 命名空间

命名空间可以避免类名冲突:

<?php
// 定义命名空间
namespace App\Models;class User {// 类定义
}// 在其他文件中使用命名空间
namespace App\Controllers;// 使用 use 语句引入类
use App\Models\User;class UserController {public function index() {$user = new User();// ...}
}// 也可以使用完全限定名称
$user = new \App\Models\User();
?>

9.3 反射

反射 API 允许在运行时检查类、接口、方法和属性:

<?php
class Person {public $name;private $age;public function __construct($name, $age) {$this->name = $name;$this->age = $age;}public function sayHello() {echo "Hello, my name is {$this->name}.";}
}// 创建反射类
$reflection = new ReflectionClass('Person');// 获取类的信息
echo "类名: " . $reflection->getName() . "\n";echo "公共方法: " . "\n";
foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {echo " - " . $method->getName() . "\n";
}echo "属性: " . "\n";
foreach ($reflection->getProperties() as $property) {echo " - " . $property->getName() . "\n";
}// 创建实例
$person = $reflection->newInstanceArgs(["张三", 30]);
$person->sayHello(); // 输出: Hello, my name is 张三.
?>

9.4 对象序列化

序列化将对象转换为字符串,反序列化则将字符串恢复为对象:

<?php
class Person {public $name;public $age;public function __construct($name, $age) {$this->name = $name;$this->age = $age;}public function sayHello() {echo "Hello, my name is {$this->name}.";}
}// 创建对象
$person = new Person("张三", 30);// 序列化对象
$serialized = serialize($person);
echo $serialized; // 输出序列化的字符串// 将序列化的字符串存储到文件
file_put_contents("person.txt", $serialized);// 从文件读取序列化的字符串
$serialized = file_get_contents("person.txt");// 反序列化对象
$unserialized = unserialize($serialized);
$unserialized->sayHello(); // 输出: Hello, my name is 张三.
?>

10. 实际应用示例

10.1 基础的 MVC 结构

<?php
// 模型(Model)
class UserModel {private $db;public function __construct($db) {$this->db = $db;}public function getUserById($id) {// 从数据库获取用户}public function saveUser($userData) {// 保存用户到数据库}
}// 视图(View)
class UserView {public function renderUserProfile($user) {// 渲染用户资料页面echo "<h1>{$user['name']}</h1>";echo "<p>Email: {$user['email']}</p>";}public function renderUserForm() {// 渲染用户表单echo "<form>...</form>";}
}// 控制器(Controller)
class UserController {private $model;private $view;public function __construct($model, $view) {$this->model = $model;$this->view = $view;}public function showProfile($id) {$user = $this->model->getUserById($id);$this->view->renderUserProfile($user);}public function showEditForm($id) {$user = $this->model->getUserById($id);$this->view->renderUserForm($user);}public function updateUser($id, $userData) {$this->model->saveUser($userData);// 重定向到用户资料页}
}// 使用示例
$db = new PDO("mysql:host=localhost;dbname=test", "root", "password");
$userModel = new UserModel($db);
$userView = new UserView();
$userController = new UserController($userModel, $userView);// 路由决定调用哪个控制器方法
$userController->showProfile(1);
?>

10.2 单例模式

<?php
// 单例模式确保一个类只有一个实例
class Database {// 保存单例实例的静态属性private static $instance = null;// 数据库连接private $connection;// 私有构造函数防止外部实例化private function __construct() {$this->connection = new PDO("mysql:host=localhost;dbname=test", "root", "password");}// 防止克隆对象private function __clone() {}// 防止反序列化private function __wakeup() {}// 获取单例实例的公共静态方法public static function getInstance() {if (self::$instance === null) {self::$instance = new self();}return self::$instance;}// 获取数据库连接public function getConnection() {return $this->connection;}
}// 使用单例
$db1 = Database::getInstance();
$db2 = Database::getInstance();// $db1 和 $db2 是同一个实例
var_dump($db1 === $db2); // 输出: bool(true)// 使用连接
$conn = $db1->getConnection();
?>

10.3 工厂模式

<?php
// 产品接口
interface Vehicle {public function drive();
}// 具体产品
class Car implements Vehicle {public function drive() {echo "Driving a car";}
}class Motorcycle implements Vehicle {public function drive() {echo "Riding a motorcycle";}
}// 工厂类
class VehicleFactory {// 工厂方法public static function createVehicle($type) {switch ($type) {case 'car':return new Car();case 'motorcycle':return new Motorcycle();default:throw new Exception("Unsupported vehicle type");}}
}// 使用工厂创建对象
$car = VehicleFactory::createVehicle('car');
$car->drive(); // 输出: Driving a car$motorcycle = VehicleFactory::createVehicle('motorcycle');
$motorcycle->drive(); // 输出: Riding a motorcycle
?>

11. 类的最佳实践

11.1 命名规范

  • 类名使用大驼峰命名法(PascalCase):User, DatabaseConnection
  • 方法名和属性名使用小驼峰命名法(camelCase):getUserById(), $firstName
  • 常量名使用全大写加下划线:MAX_CONNECTIONS, DEFAULT_TIMEOUT
  • 私有属性和方法可以使用下划线前缀:$_privateVar, _privateMethod()

11.2 代码组织

  • 将每个类放在单独的文件中
  • 使用命名空间组织类
  • 遵循 PSR 标准(特别是 PSR-1、PSR-4)
  • 使用自动加载而非手动引入

11.3 可维护性

  • 保持类的职责单一
  • 编写清晰的注释和文档
  • 使用类型声明提高代码的可靠性
  • 避免深度嵌套的继承层次
  • 优先使用组合而非继承
  • 合理使用设计模式

11.4 安全性

  • 不要在类中硬编码敏感信息
  • 使用访问控制修饰符保护类的内部状态
  • 对输入进行验证和过滤
  • 避免魔术方法的滥用
  • 注意序列化安全

12. 总结

PHP 的类和面向对象编程提供了强大的工具,使代码更有组织性、可重用性和可维护性。通过合理使用类、继承、接口、抽象类和设计模式,您可以构建复杂且灵活的应用程序。

本指南涵盖了 PHP 类的核心概念和高级特性,包括类的定义与实例化、属性与方法、访问控制、继承、多态、抽象类与接口、设计原则和实际应用示例。通过不断学习和实践,您可以进一步提升您的面向对象编程技能。


文章转载自:

http://5YPhYu74.fkffr.cn
http://8k2U18du.fkffr.cn
http://wfxfenpD.fkffr.cn
http://27pcRcCc.fkffr.cn
http://QSiYQ76D.fkffr.cn
http://8P9gefQT.fkffr.cn
http://WBV0ka65.fkffr.cn
http://ITWNL9ju.fkffr.cn
http://xsIDP0wh.fkffr.cn
http://5tgo9WLX.fkffr.cn
http://fWFpXUUS.fkffr.cn
http://S7A3tc3a.fkffr.cn
http://vvY5RPjl.fkffr.cn
http://HJCi9YAC.fkffr.cn
http://ykWsShXD.fkffr.cn
http://20i2XcTW.fkffr.cn
http://89V1rLdj.fkffr.cn
http://qqt2HXuV.fkffr.cn
http://hvhWXGvr.fkffr.cn
http://nt5ZO8mk.fkffr.cn
http://DsCI7UVk.fkffr.cn
http://iqTVzhMi.fkffr.cn
http://eFUkrTTT.fkffr.cn
http://7DJiMILf.fkffr.cn
http://jonLCb0P.fkffr.cn
http://oOac44oW.fkffr.cn
http://PmnyzH0f.fkffr.cn
http://XTW9hn6o.fkffr.cn
http://4iNZXRzg.fkffr.cn
http://Vkz96G2m.fkffr.cn
http://www.dtcms.com/a/388450.html

相关文章:

  • Android入门到实战(九):实现书架页——RecyclerView + GridLayoutManager + 本地数据库
  • 日常开发-20250917
  • 基于SpringBoot+Vue的近郊农场共享管理系统(Echarts图形化分析)
  • AI开发实战:从数据准备到模型部署的完整经验分享
  • 【漏洞预警】大华DSS数字监控系统 user_edit.action 接口敏感信息泄露漏洞分析
  • RFID赋能光伏电池片制造智能化跃迁
  • 大数据 + 分布式架构下 SQL 查询优化:从核心技术到调优体系
  • FPGA硬件设计-DDR
  • 卫星通信天线的跟踪精度,含义、测量和计算
  • 忘记MySQL root密码,如何急救并保障备份?
  • Java 异步编程实战:Thread、线程池、CompletableFuture、@Async 用法与场景
  • 贪心算法应用:硬币找零问题详解
  • while语句中的break和continue
  • 10cm钢板矫平机:一场“掰直”钢铁的微观战争
  • Python实现计算点云投影面积
  • C++底层刨析章节二:迭代器原理与实现:STL的万能胶水
  • 学习Python中Selenium模块的基本用法(14:页面打印)
  • 便携式管道推杆器:通信与电力基础设施升级中的“隐形推手”
  • leetcode 349 两个数组的交集
  • UV映射!加入纹理!
  • 车辆DoIP声明报文/识别响应报文的UDP端口规范
  • Elasticsearch 2.x版本升级指南
  • OpenCV 人脸检测、微笑检测 原理及案例解析
  • [Python编程] Python3 集合
  • [性能分析与优化]伪共享问题(perf + cpp)
  • OC-动画实现折叠cell
  • 关于层级问题
  • Linux基础命令汇总
  • getchar 和 putchar
  • 【序列晋升】35 Spring Data Envers 轻量级集成数据审计