Java学习笔记(九)

news/2024/10/30 4:25:17/

InvocationHandler

InvocationHandler 详细介绍

InvocationHandler 是 Java 反射机制中的一个接口,属于 java.lang.reflect 包。它的主要作用是为动态代理提供处理方法调用的能力。当使用 Java 动态代理时,可以通过实现 InvocationHandler 接口来定义在代理对象上调用方法时的行为。

核心方法
  • invoke(Object proxy, Method method, Object[] args):
    • proxy: 代表被代理的对象。
    • method: 被调用的方法。
    • args: 方法参数。

该方法会在每次调用代理对象的方法时被触发,你可以在这里添加额外的逻辑,比如日志、事务管理等。

AOP(面向切面编程)

AOP(Aspect-Oriented Programming)是一种编程范式,它允许你将关注点分离到不同的“切面”中。与传统 OOP 不同,AOP 可以让你将横切关注点(如日志、安全性、事务管理等)从业务逻辑中分离出来,从而提高代码的可维护性和可重用性。

AOP 和 InvocationHandler 的关系
  • 在 Java 中,Spring AOP 实际上是基于动态代理实现的,其中就使用了 InvocationHandler。当你创建一个带有切面的 Spring Bean 时,Spring 会生成一个代理类,这个类会实现目标接口,并在其内部使用 InvocationHandler 来拦截方法调用。

  • 因此,当你使用 Spring AOP 定义一个切面并应用于某个服务时,实际上是在背后利用了 InvocationHandler 来执行横切逻辑。

示例代码

以下是一个简单示例,包括自定义的 InvocationHandler 和如何通过 Spring AOP 使用它:

自定义 InvocationHandler 示例
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;// 定义接口
interface HelloService {void sayHello(String name);
}// 实现接口
class HelloServiceImpl implements HelloService {@Overridepublic void sayHello(String name) {System.out.println("Hello, " + name);}
}// 自定义 InvocationHandler
class MyInvocationHandler implements InvocationHandler {private final Object target;public MyInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 前置增强:打印日志System.out.println("Before method: " + method.getName());// 调用目标方法Object result = method.invoke(target, args);// 后置增强:打印结束信息System.out.println("After method: " + method.getName());return result;}
}public class Main {public static void main(String[] args) {HelloService helloService = new HelloServiceImpl();// 创建动态代理实例HelloService proxyInstance = (HelloService) Proxy.newProxyInstance(helloService.getClass().getClassLoader(),helloService.getClass().getInterfaces(),new MyInvocationHandler(helloService));// 调用代理实例的方法proxyInstance.sayHello("World");}
}
输出结果
Before method: sayHello
Hello, World
After method: sayHello
使用 Spring AOP 示例

如果你想要通过 Spring AOP 来实现类似功能,可以按照下面步骤进行:

  1. 添加依赖(以 Maven 为例):
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
  1. 创建服务和切面:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Service;@Service
public class HelloServiceImpl implements HelloService {@Overridepublic void sayHello(String name) {System.out.println("Hello, " + name);}
}@Aspect
@Component
class LoggingAspect {@Before("execution(* com.example.HelloService.*(..))")public void logBefore() {System.out.println("Before executing the method");}
}
  1. 启动 Spring Boot 应用程序,并调用服务:
@SpringBootApplication
public class Application {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(Application.class, args);HelloService helloService = context.getBean(HelloService.class);helloService.sayHello("World");}
}
总结
  • InvocationHandler 用于创建动态代理并处理方法调用。
  • AOP 是一种编程范式,通过切面将横切关注点从业务逻辑中分离出来。
  • 在 Spring 中,AOP 是基于动态代理实现的,因此可以看作是对 InvocationHandler 的高级封装。

MethodInterceptor 和 InvocationHandler 的关系

MethodInterceptor和InvocationHandler都是用于实现动态代理的工具,但它们在实现方式、应用场景以及效率上有所不同。以下是对两者关系的详细分析:

一、定义与实现方式
  1. InvocationHandler
  • InvocationHandler是Java动态代理的一种方式,定义在java.lang.reflect包中。
  • 通过实现InvocationHandler接口,开发者可以定义在代理对象上调用方法时要执行的逻辑。
  • InvocationHandler接口包含一个invoke()方法,该方法在代理对象的方法被调用时被触发。
  1. MethodInterceptor
  • MethodInterceptor是CGLIB库(Code Generation Library)提供的一种动态代理方式。
  • CGLIB是一个用于生成Java字节码的代码生成库,它允许在运行时对类进行代理,而不仅仅是对接口。
  • MethodInterceptor接口定义了一个intercept()方法,该方法在代理对象的方法被调用时被触发。
二、应用场景
  1. InvocationHandler
    主要用于对接口进行代理。
    由于Java的动态代理机制是基于接口的,因此InvocationHandler适用于那些需要代理的类实现了特定接口的场景。
  2. MethodInterceptor
    可以对类进行代理,而无需实现特定接口。
    由于CGLIB通过继承目标类来生成代理,因此MethodInterceptor适用于那些无法或不想实现接口的类。
三、效率与性能
  1. InvocationHandler
    由于Java的动态代理机制相对简单且直接基于接口,因此InvocationHandler通常具有较高的效率。
  2. MethodInterceptor
    由于CGLIB需要生成不同类型的字节码,并且需要生成一些运行时对象,因此MethodInterceptor的效率相对较低。
    但是,这种性能差异在大多数情况下可能并不显著,具体取决于应用程序的复杂性和性能要求。
四、总结
  1. InvocationHandler和MethodInterceptor都是实现动态代理的有效工具,但它们在实现方式、应用场景以及效率上有所不同。
  2. 如果只需要对接口进行代理,并且对效率有较高的要求,那么可以选择使用InvocationHandler。
  3. 如果需要对类进行代理,或者需要更多的控制被拦截的方法,那么可以选择使用MethodInterceptor。

综上所述,MethodInterceptor和InvocationHandler各有优劣,开发者应根据具体需求和场景选择合适的动态代理方式。

find 命令

find 命令是 Unix/Linux 系统中用于查找文件和目录的强大工具。它可以在指定的目录及其子目录中搜索符合条件的文件,并对这些文件执行操作。

基本语法
find [path] [expression]
  • path: 要搜索的路径,可以是一个或多个目录。如果不指定,默认是在当前目录。
  • expression: 用于定义查找条件,如名称、类型、大小等。
常用选项和表达式
  1. 基本查找

    • 查找特定名称的文件:

      find /path/to/search -name "filename"
      
    • 查找特定扩展名的文件:

      find /path/to/search -name "*.txt"
      
  2. 忽略大小写

    使用 -iname 选项可以忽略大小写:

    find /path/to/search -iname "*.txt"
    
  3. 按类型查找

    可以使用 -type 选项来限制查找结果:

    • 查找普通文件:

      find /path/to/search -type f
      
    • 查找目录:

      find /path/to/search -type d
      
    • 查找符号链接:

      find /path/to/search -type l
      
  4. 按时间查找

    使用 -mtime, -atime, 和 -ctime 来根据时间过滤:

    • 查找最近修改过的文件(例如:7天内):

      find /path/to/search -mtime -7 
      
    • 查找超过30天未被访问过的文件:

      find /path/to/search -atime +30 
      
  5. 按大小查找

    使用 -size 选项来根据文件大小进行筛选:

    • 找到大于100MB的文件:
      find /path/to/search -size +100M 
      
  6. 组合条件

    可以使用逻辑运算符组合多个条件:

    • -and: 与(默认)
    • -or: 或
    • !: 非

    示例:找到所有 .txt 文件并且大小大于1MB:

    find /path/to/search -name "*.txt" ! -size +1M 
    
  7. 执行命令

通过 -exec 选项可以对找到的每个文件执行命令:

find /path/to/search -name "*.tmp" -exec rm {} \;

这里 {} 是占位符,代表当前找到的每个文件,\; 表示命令结束。

  1. 打印结果

使用以下选项来控制输出格式:

  • 默认情况下,结果会逐行显示。

  • 如果需要以更易读的方式显示,可以加上 -print

find /path/to/search -name "*.log" -print 
  1. 限制深度

使用 -maxdepth-mindepth 限制搜索深度:

find /path/to/search -maxdepth 2 

这将只搜索到指定深度为2层级。

示例
  1. /home/user/ 下查找所有 .jpg 文件并删除它们:
find /home/user/ -name "*.jpg" -exec rm {} \;
  1. 找出 /var/log/ 中最后修改时间在10天前的日志文件:
find /var/log/ -mtime +10 
  1. 查找到大于500KB且以 .pdf 结尾的所有文档,并列出详细信息:
find . \( -name "*.pdf" \)  \( ! –size –500k \) –ls 
总结

find 命令非常灵活和强大,能够满足多种需求。通过合理地组合各种参数和表达式,可以高效地管理和处理大量数据。在实际使用中,根据具体需求调整路径和条件,以达到最佳效果。

mysql 创建用户方式

在 MySQL 中,创建用户是数据库管理的重要任务之一。MySQL 提供了多种方式来创建用户,包括使用 SQL 语句、图形界面工具(如 MySQL Workbench)等。下面将详细介绍通过 SQL 语句创建用户的步骤,并给出示例。

创建用户的基本步骤
  1. 连接到 MySQL 数据库:使用具有足够权限的账户(如 root 用户)登录到 MySQL。
  2. 执行 CREATE USER 语句:使用 SQL 命令创建新用户。
  3. 授予权限:为新用户分配所需的权限,以便他们可以执行特定操作。
创建用户的 SQL 语法
CREATE USER 'username'@'host' IDENTIFIED BY 'password';
  • username: 要创建的用户名。
  • host: 用户可以从哪个主机连接到数据库。常见值有:
    • 'localhost':仅允许本地连接。
    • '%':允许任何主机连接。
  • password: 用户密码。
示例
第一步:连接到 MySQL

首先,打开命令行并输入以下命令以登录到 MySQL:

mysql -u root -p

系统会提示你输入 root 用户的密码。

第二步:创建一个新用户

假设我们要创建一个名为 newuser 的新用户,该用户可以从任何主机访问,并且其密码为 password123

CREATE USER 'newuser'@'%' IDENTIFIED BY 'password123';
第三步:授予权限

接下来,我们需要为该用户授予必要的权限。例如,如果我们希望 newuser 可以对数据库进行所有操作,可以使用以下命令:

GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'%';

这条命令表示给予 newuser 对所有数据库和表格的所有权限。如果只想授权某个特定数据库,例如名为 mydatabase 的数据库,可以这样做:

GRANT ALL PRIVILEGES ON mydatabase.* TO 'newuser'@'%';
第四步:刷新权限

为了确保新的权限生效,可以运行以下命令:

FLUSH PRIVILEGES;
完整示例代码

结合上述步骤,完整示例如下:

-- 登录到 MySQL (在命令行中)
mysql -u root -p;-- 创建新用户
CREATE USER 'newuser'@'%' IDENTIFIED BY 'password123';-- 授予所有权限(或指定数据库)
GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'%';-- 刷新权限
FLUSH PRIVILEGES;
注意事项
  1. 安全性: 使用强密码以保护你的数据库安全。
  2. 最小权限原则: 尽量不要给予过多不必要的权限,只授予必需的最低限度权利,以减少潜在风险。
  3. 主机限制: 如果你只希望特定 IP 或域名能够访问该账户,请替换 % 为具体地址,如 '192.168.1.%''example.com'

http://www.ppmy.cn/news/1542993.html

相关文章

IBM刚刚发布了第三代Granite大型语言模型

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Docker Compose一键部署Spring Boot + Vue项目

目录 前提条件 概述 Compose简介 Compose文件 Compose环境 Compose命令 帮助命令 关键命令 Compose部署项目 初始化环境 查看代码文件 sql数据准备 nginx配置文件准备 创建 compose.yaml 一键启动compose多个容器 浏览器访问虚拟机ip:80(可省略默认的80端口) …

高级java每日一道面试题-2024年10月23日-JVM篇-说一下JVM有哪些垃圾回收算法?

如果有遗漏,评论区告诉我进行补充 面试官: 说一下JVM有哪些垃圾回收算法? 我回答: 在 Java 虚拟机 (JVM) 中&#xff0c;垃圾回收 (Garbage Collection, GC) 是一项非常重要的功能&#xff0c;用于自动管理应用程序的内存。JVM 采用多种垃圾回收算法来决定何时以及如何回收…

大数据新视界 -- 大数据大厂之大数据重塑影视娱乐产业的未来(4 - 3)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

java中Scanner的nextLine和next方法

思考&#xff0c;输入1 2 3 4 5加上enter&#xff0c;输出什么 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int[][] m new int[2][2];for (int i 0; i < 2; i) {for (int j 0; j < 2;…

`a = a + b` 与 `a += b` 的区别

在 Java 中&#xff0c;a a b 和 a b 都用于将 b 的值加到 a 上&#xff0c;但它们之间存在一些重要的区别&#xff0c;尤其是在类型转换和操作行为方面。 使用 操作符时&#xff0c;Java 会自动进行隐式类型转换&#xff0c;而使用 则不会。这意味着在 a b 的情况下&am…

工具_Nginx

文章目录 location语法介绍跨域配置https配置http重定向到https配置反向代理配置负载均衡配置upstream配置负载均衡算法&#xff08;1&#xff09;rr轮询&#xff08;默认&#xff09;&#xff08;2&#xff09;wrr加权轮询&#xff08;weight&#xff09;&#xff08;3&#x…

CI/CD 的原理

一、CI/CD 的概念 CI/CD是一种软件开发流程&#xff0c;旨在通过自动化和持续的集成、测试和交付实现高质量的软件产品。 CI(Continuous Integration)持续集成 目前主流的开发方式是协同开发&#xff0c;即多位开发人员同事处理同意应用不同模块或功能。 如果企业在同一时间将…