图片外链网站html5教程初学者

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

图片外链网站,html5教程初学者,做网站开发的薪酬怎么样,网站访问者1.Spring AOP (Aspect-Oriented Programming) 1. 1. 什么是 Spring AOP#xff1f; AOP#xff08;面向切面编程#xff09; 是 Spring 提供的一种可插拔的组件技术#xff0c;允许我们在软件运行过程中添加额外的功能。场景#xff1a;假设有两个模块#xff0c;用户管…1.Spring AOP (Aspect-Oriented Programming) 1. 1. 什么是 Spring AOP AOP面向切面编程 是 Spring 提供的一种可插拔的组件技术允许我们在软件运行过程中添加额外的功能。场景假设有两个模块用户管理模块A和员工管理模块B。现在需要在业务处理过程中添加权限过滤功能。 如果在两个模块中都添加权限判断代码当权限需求变化时需要再次修改代码这样会增加开发和维护成本。使用 Spring AOP我们可以将权限判断的代码独立为一个切面在代码执行前进行权限过滤而不需要修改原业务逻辑。 1. 2. 面向切面编程 (AOP) 的核心概念 切面Aspect表示横切的功能模块用于实现某些通用功能如权限检查、日志记录等。切面可以在方法执行前后插入。权限切面在执行业务逻辑之前判断用户权限。日志切面记录业务逻辑的执行时间、输入参数、输出结果等信息。 通过切面技术日志和权限判断代码可以在不修改业务代码的情况下被“织入”程序。如果业务需求发生变化只需调整配置即可轻松移除切面不影响核心业务逻辑。 1. 3. 切面与插件技术的类比 切面类似于我们在浏览器中安装的插件可以为现有的业务模块增加额外的功能。 例如安装翻译插件后浏览器可以将英文网页自动翻译为中文。一旦不需要这些功能卸载插件即可还原浏览器的原始状态。切面也是如此它为业务模块提供了额外的功能但这些模块本身不会感知到切面的存在。 1. 4. 为什么叫“切面” 正常的软件执行流程是从上到下按照代码顺序执行的而切面则像一个横切面在执行过程中横插进入业务流程中。 这些横切的功能模块就是所谓的“切面Aspect”通过切面我们可以为现有的业务逻辑增加扩展功能。 1. 5. AOP 的最终目的 不修改源码 的情况下扩展程序行为。通常将与业务无关的通用功能如权限检查、日志记录封装为切面类通过配置来插入这些功能。切面可以配置在目标方法的执行前、执行后达到真正的“即插即用”。 2.Spring AOP - 实战配置项目 课程简介 本节课程将通过实际项目配置带领大家一步一步理解 Spring AOP面向切面编程的功能。我们将基于 XML 配置的形式来实现 AOP并通过演示了解 AOP 如何对现有系统进行功能扩展而无需修改源代码。 2. 1. 项目结构介绍 本次演示基于 s01 工程其中包含了两个主要部分 DAO 层包括 EmployeeDao 和 UserDao分别用于对员工表和用户表的数据增删改查。Service 层包括 EmployeeService 和 UserService分别提供了员工相关的业务逻辑和用户管理的业务逻辑。 EmployeeService提供 entry 方法模拟员工入职操作。UserService提供 createUser 方法创建用户和 generateRandomPassword 方法生成随机密码。
这些类的业务逻辑非常常规但本节课我们将通过 AOP 实现对方法执行时间的监控解决手动添加代码带来的冗余和复杂度问题。 2. 2. 需求描述 我们希望在系统运行过程中对所有 Service 层和 DAO 层的方法调用前打印执行时间从而便于分析系统负载高峰时间。 问题 如果直接在每个方法中手动添加 System.out.println() 代码维护和删除这些代码将变得非常麻烦。AOP 可以在不修改原代码的情况下灵活地添加或移除这些功能。 2. 3. 配置项目依赖 首先我们需要在 pom.xml 文件中添加必要的依赖项 dependencies!– Spring context dependency –dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.2.6.RELEASE/version/dependency!– AspectJ Weaver (AOP 底层依赖) –dependencygroupIdorg.aspectj/groupIdartifactIdaspectjweaver/artifactIdversion1.9.5/version/dependency /dependenciesspring-context 是用来初始化 IOC 容器的基础依赖而 aspectjweaver 则是 AOP 的底层依赖负责切面功能的实现。 2. 4. 配置 applicationContext.xml 接下来我们需要在 resources 目录下创建 applicationContext.xml 文件这是 Spring IOC 的配置文件。 添加命名空间 beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd!– 配置 Beans –bean iduserDao classcom.example.dao.UserDao /bean idemployeeDao classcom.example.dao.EmployeeDao /bean iduserService classcom.example.service.UserServiceproperty nameuserDao refuserDao //beanbean idemployeeService classcom.example.service.EmployeeServiceproperty nameemployeeDao refemployeeDao //bean /beans引入 aop 命名空间 该命名空间用于配置 AOP 所需的相关标签。它将帮助我们在不修改源代码的前提下为现有方法添加执行时间打印功能。 2. 5. 初始化 IOC 容器并执行测试 接下来我们在 aop 包下创建一个 Spring 应用的入口类 public class SpringApplication {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml);UserService userService context.getBean(userService, UserService.class);userService.createUser(); // 模拟创建用户的过程} }运行代码后可以看到控制台输出显示了 UserService 和 UserDao 中各个方法的执行情况。 2. 6. Spring AOP - 方法执行时间打印需求实现 课程目标 通过 AOP 实现对 Service 或 DAO 层中任意方法的执行时间进行打印并避免在每个方法中手动增加日志打印代码。AOP 能够灵活地实现这些功能且无需修改源代码。 1. 新增切面类 (Method Aspect) 在 AOP 配置中我们需要创建一个切面类用于扩展业务逻辑。在 aop 包下新增一个 aspect 包创建切面类 MethodAspect用于打印方法的执行时间。 切面类 MethodAspect public class MethodAspect {public void printExecutionTime(JoinPoint joinPoint) {// 获取当前时间并格式化SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd HH:mm:ss.SSS);String now sdf.format(new Date());// 获取目标类名和方法名String className joinPoint.getTarget().getClass().getName();String methodName joinPoint.getSignature().getName();// 打印执行时间信息System.out.println(—–);System.out.println(Time: now);System.out.println(Class: className);System.out.println(Method: methodName);System.out.println(—–);} }JoinPoint 参数用于获取目标类和目标方法的信息。printExecutionTime() 方法会在目标方法执行前打印当前时间、类名和方法名。 2. AOP 配置文件 applicationContext.xml 在 applicationContext.xml 文件中进行 AOP 配置使得在调用 Service 或 DAO 方法时自动打印方法的执行时间。 配置 AOP 切面 bean idmethodAspect classcom.example.aspect.MethodAspect /aop:config!– 定义切点匹配 com.example 包下所有类的所有 public 方法 –aop:pointcut idserviceMethods expressionexecution(public * com.example..*(..)) /!– 定义切面 –aop:aspect refmethodAspect!– 前置通知在方法执行前打印执行时间 –aop:before methodprintExecutionTime pointcut-refserviceMethods //aop:aspect /aop:configaop:pointcut 定义了切点匹配 com.example 包下的所有 public 方法。aop:before 定义了前置通知表示在目标方法执行之前调用 printExecutionTime() 方法。 3. AOP 运行效果

在运行程序时任何 Service 或 DAO 层方法执行前控制台都会打印方法执行的时间、类名和方法名。示例输出

Time: 2024-10-16 10:35:12.123 Class: com.example.service.UserService Method: createUser —–关闭功能 如果项目经理不再需要打印时间信息只需注释掉 AOP 的配置部分即可。 3. Spring AOP - 关键概念与配置解析

  1. 1. Spring AOP 和 AspectJ 的关系 AspectJ一种基于 Java 平台的面向切面编程AOP语言提供完整的 AOP 编程体系。Spring AOPSpring 提供的 AOP 实现部分依赖 AspectJ。AspectJ 主要用于类和方法的匹配通过 aspectjweaver而功能的增强由 Spring 本身通过代理模式实现。 3. 2. 关键概念 2.1 切面Aspect 切面具体的可插拔组件功能类通常用于实现通用功能。切面类一个标准的 Java 类无需继承或实现其他类。可以包含多个切面方法这些方法用于实现功能扩展。切面方法 例如printExecutionTime() 用于打印方法的执行时间。方法必须为 public返回值可以是 void 或 Object具体取决于通知类型。需包含 JoinPoint 参数用于获取目标类和方法的信息。
    2.2 连接点JoinPoint 连接点获取目标类和目标方法的元数据对象。可通过 joinPoint.getTarget() 获取目标对象通过 joinPoint.getSignature().getName() 获取目标方法名。 2.3 切点Pointcut 切点用于定义切面要作用的范围。通过 execution 表达式指定切面应在哪些类的哪些方法上生效。切点表达式在配置文件中使用 expression 属性指定作用范围。 示例execution(public * com.example..*(..)) 作用于 com.example 包下所有类的所有 public 方法。
    2.4 通知Advice 通知Advice指定切面方法在何时执行。Spring AOP 支持五种通知类型 前置通知Before在目标方法执行前执行。后置通知After在目标方法执行后执行。其他类型包括返回后通知、异常通知、环绕通知。
    2.5 目标类和目标方法 目标类和目标方法指真正执行业务逻辑的类和方法例如 Service 或 DAO 层中的 createUser() 或 insert() 方法。 3. 3. AOP 配置步骤 通过 XML 配置 AOP 主要包含以下五个步骤 3.1 引入 AspectJ 依赖 在 pom.xml 中引入 aspectjweaver 依赖 dependencygroupIdorg.aspectj/groupIdartifactIdaspectjweaver/artifactIdversion1.9.5/version /dependency3.2 实现切面类和方法 切面类是一个标准的 Java 类方法中需包含 JoinPoint 参数用于获取目标类和方法的信息。 3.3 配置切面类 在 applicationContext.xml 中配置切面类 bean idmethodAspect classcom.example.aspect.MethodAspect /3.4 定义切点 使用 pointcut 标签定义切点指定切面的作用范围 aop:pointcut idserviceMethods expressionexecution(public * com.example..*(..)) /3.5 配置通知Advice 在目标方法执行前通过 before 标签调用切面方法 aop:before methodprintExecutionTime pointcut-refserviceMethods /4. Spring AOP - JoinPoint 连接点核心方法

  2. 1. JoinPoint 连接点简介 JoinPoint 连接点用于获取目标类和目标方法的相关信息能够在切面方法中通过 JoinPoint 参数访问这些信息。JoinPoint 提供了三个核心方法分别是 getTarget()获取目标对象由 IOC 容器管理的对象。getSignature()获取目标方法的签名信息。getArgs()获取目标方法的实际参数。 4. 2. 核心方法介绍与演示 2.1 getTarget() 方法 作用获取由 IOC 容器管理的目标对象。演示 在切面方法中调用 joinPoint.getTarget() 可以获取目标对象再通过 getClass().getName() 获取该目标对象所属的类名。
    2.2 getSignature() 方法 作用获取目标方法的签名。演示 使用 joinPoint.getSignature().getName() 获取目标方法的名称。
    2.3 getArgs() 方法 作用获取目标方法调用时传入的参数。演示 joinPoint.getArgs() 返回一个 Object 数组表示传入的参数。可以对该数组进行遍历并打印每个参数的值。 5. Spring AOP - Pointcut 切点表达式详解

  3. 1. Pointcut 切点的作用 Pointcut 切点用于告诉 AOP 哪些类的哪些方法应该应用切面逻辑。切点表达式的作用定义切面生效的范围。 5. 2. 方法结构与切点表达式 一个完整的方法结构包含以下部分 修饰符如 public、private 等。返回值类型如 void、String。类的完整路径如 com.example.service.UserService。方法名及参数如 createUser()。 切点表达式的作用是匹配这些方法结构中的各个部分。它与方法结构一一对应。 5. 3. 切点表达式 execution 详解 execution 表达式用于指定切面生效的范围。其格式为 execution([修饰符] [返回值] [类路径].[类名].方法名)3.1 常见的通配符 *匹配任意返回值、类名、方法名等。..包通配符匹配当前包及子包中的所有类或任意数量的参数。 5. 4. 实例讲解 4.1 匹配所有类的所有公共方法 aop:pointcut expressionexecution(public * com.example..(..)) /匹配 com.example 包及其子包下的所有类的 public 方法。 表示任意返回值。.. 表示任意包路径的匹配。(..) 表示任意方法和任意参数。
    4.2 匹配特定类名结尾的类 aop:pointcut expressionexecution(
    com.example..Service.(..)) /匹配 Service 结尾的类中的所有方法。 4.3 匹配返回 void 的方法 aop:pointcut expressionexecution(void com.example..Service.(..)) /匹配返回类型为 void 的方法。 4.4 匹配返回 String 的方法 aop:pointcut expressionexecution(String com.example..Service.(..)) /匹配返回类型为 String 的方法。 4.5 匹配以 create 开头的方法 aop:pointcut expressionexecution(* com.example..Service.create(..)) /匹配方法名以 create 开头的方法。 4.6 匹配无参数的方法 aop:pointcut expressionexecution(* com.example..Service.()) /匹配无参数的方法。 4.7 匹配有特定数量参数的方法 aop:pointcut expressionexecution(* com.example..Service.(String, int)) /匹配参数为 String 和 int 类型的方法。 6. Spring AOP - 五种通知类型

  4. 1. 通知Advice的概念 通知 是指在什么时机去执行切面的方法。Spring AOP 提供了五种类型的通知每种通知对应不同的执行时机。 6. 2. 五种通知类型详解 2.1 前置通知Before Advice 作用在目标方法运行前执行切面方法。示例在用户创建方法前输出日志信息。 2.2 返回后通知After Returning Advice 作用在目标方法返回结果后执行切面方法。特点可以获取目标方法的返回值。示例在用户创建成功后输出返回结果或状态。 2.3 异常通知After Throwing Advice 作用在目标方法抛出异常后执行切面方法。特点可以获取并处理目标方法抛出的异常。示例捕获用户创建时的异常并输出相关信息。 2.4 后置通知After Advice 作用在目标方法执行完毕后无论是否成功执行切面方法。特点类似于 finally 块无论是否抛出异常后置通知都会执行。示例在用户创建操作结束后输出日志。 2.5 环绕通知Around Advice 作用可以自定义通知的执行时机并且决定目标方法是否执行。特点功能最强大可以完全控制方法的执行流程。示例在用户创建方法前后执行额外的操作并根据条件决定是否继续执行目标方法。 6. 3. After 类型通知的执行顺序 After Returning 和 After Throwing 是互斥的 After Returning 在目标方法成功返回后执行。After Throwing 在目标方法抛出异常时执行。 After Advice无论成功与否都会执行类似于 try-catch-finally 结构中的 finally。 6. 4. 示例代码后置通知 public void doAfter(JoinPoint joinPoint) {System.out.println(后置通知触发); }配置后置通知 aop:after methoddoAfter pointcut-refservicePointCut /6. 5. 返回后通知与异常通知的示例 5.1 返回后通知 public void doAfterReturning(JoinPoint joinPoint, Object retVal) {System.out.println(返回后通知返回值: retVal); }配置返回后通知 aop:after-returning methoddoAfterReturning pointcut-refservicePointCut returningretVal /5.2 异常通知 public void doAfterThrowing(JoinPoint joinPoint, Throwable error) {System.out.println(异常通知异常信息: error.getMessage()); }配置异常通知 aop:after-throwing methoddoAfterThrowing pointcut-refservicePointCut throwingerror /6. 6. 特殊通知引介增强Introduction Advice 作用可以为类动态添加新的属性或方法类似于动态代理。特点与其他通知不同它作用于类的增强而非方法的增强。场景在运行时根据不同的环境动态改变类的行为。 6. 7. 结论 前四种通知类型各有用途了解它们的执行时机和特点非常重要特别是在调试和监控时。环绕通知是最强大的通知类型能够完全控制方法的执行流程。引介增强是高级应用允许在运行时为类动态添加行为使用场景较为特殊。

  5. Spring AOP - 环绕通知案例

  6. 1. 场景介绍 在实际工作中随着用户量和数据量的增长系统可能会变慢。为了定位具体是哪个方法执行缓慢我们可以利用环绕通知来记录每个方法的执行时间并将超过预定时间阈值的方法记录下来便于后续优化。环绕通知 是 Spring AOP 中最强大的通知类型可以完整控制目标方法的执行周期。 7. 2. 环绕通知的使用方法 环绕通知 可以在目标方法执行前、执行后获取时间计算出方法的执行时长。通过 ProceedingJoinPoint 参数可以控制目标方法是否执行。 示例代码环绕通知 public Object checkExecutionTime(ProceedingJoinPoint pjp) throws Throwable {// 记录开始时间long startTime new Date().getTime();// 执行目标方法Object retVal pjp.proceed();// 记录结束时间long endTime new Date().getTime();long executionTime endTime - startTime;// 如果执行时间超过1秒输出日志if (executionTime 1000) {System.out.println(方法执行时间过长 executionTime 毫秒);}// 返回目标方法的执行结果return retVal; }7. 3. 环绕通知的关键点 ProceedingJoinPointProceedingJoinPoint 是 JoinPoint 的升级版除了获取目标方法的信息还可以控制目标方法的执行。 关键方法proceed()用于执行目标方法并返回结果。 执行时间的记录在方法执行前记录开始时间执行后记录结束时间然后计算执行时长。异常处理环绕通知可以捕获并处理目标方法抛出的异常。 7. 4. 配置环绕通知 在 applicationContext.xml 中配置环绕通知 bean idmethodChecker classcom.example.aspect.MethodChecker /aop:configaop:pointcut idservicePointCut expressionexecution(* com.example..Service.(..)) /aop:aspect refmethodCheckeraop:around methodcheckExecutionTime pointcut-refservicePointCut //aop:aspect /aop:config7. 5. 环绕通知与其他通知的比较 环绕通知 可以完成其他四种通知的所有工作 方法执行前相当于 前置通知。方法执行后相当于 后置通知。返回值可以通过 返回后通知 处理。异常处理则对应 异常通知。 因此环绕通知是最为灵活和强大的通知类型。 7. 6. 总结 环绕通知可以控制目标方法的完整生命周期并通过 ProceedingJoinPoint 来决定是否执行目标方法。使用环绕通知我们可以轻松捕捉方法的执行时间、处理返回值以及异常。了解环绕通知的工作原理后你可以灵活运用它来解决复杂的系统性能问题。

  7. Spring AOP - 基于注解的配置

  8. 1. 基于注解的 AOP 简介 之前我们通过 XML 配置 Spring AOP虽然功能强大但配置较为繁琐。Spring 提供了基于注解的方式简化了 AOP 的配置将配置信息从 XML 移动到源代码中。 8. 2. 配置步骤 2.1 引入依赖 在 pom.xml 中引入 Spring 和 AspectJ 相关依赖 dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.2.6.RELEASE/version /dependency dependencygroupIdorg.aspectj/groupIdartifactIdaspectjweaver/artifactIdversion1.9.5/version /dependency2.2 配置 applicationContext.xml 在 applicationContext.xml 中启用注解扫描和 AOP 注解模式 context:component-scan base-packagecom.example / aop:aspectj-autoproxy /component-scan扫描指定包下的组件。aspectj-autoproxy启用 Spring AOP 注解模式。 8. 3. 在源代码中使用注解 3.1 Service 和 DAO 注解 在 Service 和 DAO 类上使用 Service 和 Repository 注解将它们注册到 Spring IOC 容器中 Service public class UserService {Resourceprivate UserDao userDao;// Service 方法 }Repository public class UserDao {// DAO 方法 }3.2 切面类配置 创建切面类 MethodChecker并使用注解定义环绕通知 Component Aspect public class MethodChecker {Around(execution(* com.example..Service.(..)))public Object checkExecutionTime(ProceedingJoinPoint pjp) throws Throwable {// 记录开始时间long startTime new Date().getTime();// 执行目标方法Object retVal pjp.proceed();// 记录结束时间long endTime new Date().getTime();long executionTime endTime - startTime;// 如果方法执行时间超过1秒记录日志if (executionTime 1000) {System.out.println(方法执行时间过长 executionTime 毫秒);}// 返回目标方法的执行结果return retVal;} }Component将 MethodChecker 注册为 Spring IOC 容器的组件。Aspect表明该类是一个切面类。Around定义环绕通知并通过 execution 表达式指定切点。 8. 4. 其他通知注解 除了 Around还有其他几种通知注解 Before前置通知在目标方法执行前调用。After后置通知在目标方法执行后调用。AfterReturning返回后通知在目标方法成功返回后调用。AfterThrowing异常通知在目标方法抛出异常时调用。 8. 5. 总结 基于注解的 Spring AOP 配置大大简化了开发过程只需在代码中添加注解即可完成配置。Aspect 和 Around 等注解可以帮助我们灵活地实现切面逻辑而无需繁琐的 XML 配置。通过组件扫描和 AOP 自动代理Spring 可以轻松管理切面和服务类的生命周期。

  9. Spring AOP - 代理模式与实现原理

  10. 1. Spring AOP 的底层实现原理 Spring AOP 的底层核心是基于设计模式中的 代理模式用于实现功能的动态扩展。Spring AOP 的实现方式有两种 JDK 动态代理当目标类实现了接口时使用 JDK 动态代理来实现。CGLIB当目标类没有实现接口时使用 CGLIB 进行代理。 9. 2. 代理模式的基本概念 代理模式 是通过代理对象对原对象进行功能扩展的设计模式。代理对象代表真正执行业务逻辑的对象并在其基础上添加额外的功能。生活中的例子租房时中介作为代理人帮助客户租客和房东进行交易完成租房过程。 9. 3. 静态代理的实现 3.1 接口定义 创建一个 UserService 接口定义用户服务的基础功能 public interface UserService {void createUser(); }3.2 委托类实现 创建 UserServiceImpl 类作为接口的具体实现类负责用户创建的实际业务逻辑 public class UserServiceImpl implements UserService {Overridepublic void createUser() {System.out.println(执行创建用户业务逻辑);} }3.3 代理类实现 通过创建代理类 UserServiceProxy 来扩展 UserService 接口的功能 public class UserServiceProxy implements UserService {private UserService userService;// 构造方法接受委托类的对象public UserServiceProxy(UserService userService) {this.userService userService;}Overridepublic void createUser() {// 扩展功能打印方法执行前的时间System.out.println(执行前时间: new SimpleDateFormat(yyyy-MM-dd HH:mm:ss).format(new Date()));// 调用委托类的实际业务逻辑userService.createUser();// 扩展功能可以在这里添加更多逻辑} }9. 4. 动态代理的嵌套 通过创建多个代理类可以实现代理嵌套 public class UserServiceProxy1 implements UserService {private UserService userService;public UserServiceProxy1(UserService userService) {this.userService userService;}Overridepublic void createUser() {// 调用委托类的方法userService.createUser();// 扩展功能在方法执行后进行额外处理System.out.println(方法后扩展功能);} }可以使用多个代理类进行嵌套代理通过一层层扩展功能。 9. 5. 示例代码静态代理的调用 在 Application 类中调用代理类实现方法的功能扩展 public class Application {public static void main(String[] args) {// 实例化委托类UserService userService new UserServiceImpl();// 使用代理类对委托类进行扩展UserService proxy new UserServiceProxy(new UserServiceProxy1(userService));proxy.createUser();} }9. 6. 静态代理的缺点 每增加一个业务类都需要手动创建相应的代理类导致代码冗余和复杂度增加。如果系统中有大量的业务类则需要编写大量的代理类这样会使系统变得笨重。 10. JDK动态代理课程笔记

  11. 1. 引言 静态代理: 手动创建代理类代理类持有目标对象的引用并在实现方法中扩展业务逻辑。 要点: 代理类和委托类必须实现相同的接口。代理类需要持有委托类的对象。 问题: 手动创建大量代理类会导致工作量庞大。

  12. 2. JDK动态代理概述 引入: JDK 12后使用反射机制自动生成代理类。动态代理: 代理类在运行时根据接口结构生成而不需要手动书写。区别: 静态代理手动编写动态代理则在内存中动态生成。

  13. 3. 代码实现步骤 3.1 创建工程 创建新的工程设置 group ID 和 artifact工程名为 s05。 3.2 编写代码 复制之前的 UserService 接口和 UserServiceImpl 实现类。 3.3 创建 ProxyInvocationHandler 在 service 包中创建 ProxyInvocationHandler 类实现 InvocationHandler 接口。实现 invoke 方法: 参数: proxy: 代理类对象由JDK动态代理生成。method: 目标方法信息。args: 目标方法的实际参数。 实现逻辑: 输出当前时间。调用目标方法并返回结果。
    public class ProxyInvocationHandler implements InvocationHandler {private Object target;public ProxyInvocationHandler(Object target) {this.target target;}Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(当前时间: System.currentTimeMillis());return method.invoke(target, args);} }3.4 使用 ProxyInvocationHandler 在 main 方法中 创建目标对象 UserService userService new UserServiceImpl()。实例化 ProxyInvocationHandler传入目标对象。使用 Proxy.newProxyInstance 创建代理类。
    public static void main(String[] args) {UserService userService new UserServiceImpl();ProxyInvocationHandler handler new ProxyInvocationHandler(userService);UserService proxy (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),userService.getClass().getInterfaces(),handler);proxy.createUser(); }10. 4. 注意事项 接口要求: JDK动态代理必须实现接口如果类不实现接口则无法使用此机制。Spring解决方案: 对于不实现接口的类Spring提供CGlib库实现类的增强。

  14. JDK动态代理原理与实现细节课程笔记

  15. 1. 引言 本课程通过源代码的回顾深入探讨JDK动态代理的底层原理和实现细节。

    1. 重要概念 Proxy.newProxyInstance: JDK 反射包中的一个方法用于根据接口生成对应的代理类。由于JDK底层实现过程不可见通过图示化理解其执行过程将更加有助于掌握。

      11. 3. 执行过程

      3.1 创建代理类 执行 Proxy.newProxyInstance 时会经历三个主要步骤 生成字节码文件: 在本地硬盘上创建一个 .class 文件默认存放在 com.sun.proxy 包下。类名格式为 \(Proxy0以 \) 开头加上数字。生成代理类: 代理类实现了原有的接口。定义类: 通过 defineClass 方法将字节码文件加载到JVM的方法区中。
      3.2 伪代码示例 public class \(Proxy0 implements UserService {private UserService target;public \)Proxy0(UserService target) {this.target target;}public void createUser() {System.out.println(执行前置逻辑);target.createUser();} }该伪代码展示了生成的代理类结构持有目标对象的引用。

    1. JVM内存操作 代理对象被创建并保存到JVM的堆内存中持有被代理类的引用。当调用 userServiceProxy.createUser() 时实际上会执行生成的代理类中的逻辑。
  16. Spring AOP与CGlib课程笔记

    1. 引言 上一节课使用代码演示了如何通过JDK动态代理实现Spring AOP功能。JDK动态代理要求目标类必须实现接口但在实际应用中许多类并不实现接口这时需要其他解决方案。
    1. CGlib介绍 CGlib: Code Generation Library的缩写是一种运行时字节码增强技术。Spring AOP使用CGlib来扩展没有实现接口的类。当一个类没有实现接口时AOP会在运行时生成目标类的继承字节码从而进行行为扩展。
    1. CGlib原理 假设有一个Service类包含一个findById方法但该类没有实现接口。由于无法使用JDK动态代理Spring会自动使用CGlib通过继承来对类进行扩展。生成的子类类名格式为OriginalClassName$$EnhancerByCGLIB。 3.1 继承与方法重写 子类会重写父类中的findById方法逻辑如下 执行自定义前置处理代码。调用父类的findById方法使用super.findById()。执行自定义后置处理代码。
    1. 示例演示 通过之前写好的实例来展示CGlib的使用。在S03工程中UserService类没有实现任何接口。断点调试程序可以看到生成的类名包含$$EnhancerBySpringCGLIB表明使用CGlib进行增强。
    1. 变更为接口实现 将UserService类修改为实现一个接口IUserService。修改引用为IUserService保持方法调用部分不变。断点调试生成的对象类名变为proxy表示使用了JDK动态代理。
    1. AOP实现原理总结 两种情况: 如果目标类实现了接口Spring优先使用JDK动态代理生成代理类。如果目标类没有实现接口则使用CGlib通过继承对目标类进行扩展。 了解这些细节在面试中回答Spring AOP实现原理时非常重要。