面向切面编程和面向对象编程的区别,两者有冲突吗?
面向切面编程AOP和面向对象编程OOP是两种不同的编程范式它们各自解决不同类型的问题并且通常可以互补使用而不是冲突。OOP 关注的是对象和它们的交互强调的是数据和行为的封装。AOP关注的是横切关注点强调的是将与业务无关的代码如日志、事务从业务逻辑中分离出来。AOP 和 OOP 是互补的。OOP 关注的是业务逻辑的实现和数据的封装而 AOP 关注的是横切关注点的管理。你可以在 OOP 代码中使用 AOP 来简化和管理横切关注点。并且AOP 通常在 OOP 代码的基础上实现。例如 AOP 框架如 AspectJ、Spring AOP都是基于 OOP 语言如Java实现的。AOP有哪些实现方式AOP有两种实现方式静态代理和动态代理。静态代理静态代理代理类在编译阶段生成在编译阶段将通知织入Java字节码中也称编译时增强。AspectJ使用的是静态代理。缺点代理对象需要与目标对象实现一样的接口并且实现接口的方法会有冗余代码。同时一旦接口增加方法目标对象与代理对象都要维护。动态代理动态代理代理类在程序运行时创建AOP框架不会去修改字节码而是在内存中临时生成一个代理对象在运行期间对业务方法进行增强不会生成新类。Spring AOP的实现原理Spring的AOP实现原理其实很简单就是通过动态代理实现的。如果我们为Spring的某个bean配置了切面那么Spring在创建这个bean的时候实际上创建的是这个bean的一个代理对象我们后续对bean中方法的调用实际上调用的是代理类重写的代理方法。而Spring的AOP使用了两种动态代理分别是JDK的动态代理以及CGLib的动态代理。底层实现主要分两部分创建AOP动态代理和调用代理在启动Spring会创建AOP动态代理首先通过AspectJ解析切点表达式在创建代理对象时Spring AOP使用AspectJ来解析切点表达式。它会根据定义的条件匹配目标Bean的方法。如果Bean不符合切点的条件将跳过否则将会通动态代理包装Bean对象具体会根据目标对象是否实现接口来选择使用JDK动态代理或CGLIB代理。这使得AOP可以适用于各种类型的目标对象。在调用阶段Spring AOP使用责任链模式来管理通知的执行顺序。通知拦截链包括前置通知、后置通知、异常通知、最终通知和环绕通知它们按照配置的顺序形成链式结构。通知的有序执行 责任链确保通知按照预期顺序执行。前置通知在目标方法执行前执行后置通知在目标方法成功执行后执行异常通知在方法抛出异常时执行最终通知无论如何都会执行而环绕通知包裹目标方法允许在方法执行前后添加额外的行为。综上所述Spring AOP在创建启动阶段使用AspectJ解析切点表达式如果匹配使用动态代理而在调用阶段使用责任链模式确保通知的有序执行。这些机制共同构成了Spring AOP的底层实现。Spring AOP 和 AspectJ AOP 有什么区别Spring AOP 属于运行时增强而 AspectJ 是编译时增强。Spring AOP 基于代理(Proxying)而 AspectJ 基于字节码操作(Bytecode Manipulation)。Spring AOP 已经集成了 AspectJ AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大但是 Spring AOP 相对来说更简单如果我们的切面比较少那么两者性能差异不大。但是当切面太多的话最好选择 AspectJ 它比 Spring AOP 快很多。Spring AOP是 Spring 框架提供的一种 AOP 实现主要用于运行时的代理机制。特点Spring AOP 是基于动态代理实现的适用于Spring 容器管理的 Bean较轻量级使用方便。使用场景适合大部分业务场景尤其是需要简单 AOP 功能的 Spring 应用。AspectJAspectJ 是功能更强大的 AOP 框架支持编译时、类加载时和运行时的 AOP 功能。特点AspectJ 支持更加灵活的切点和增强操作提供编译期和加载期的织入方式性能较高。使用场景适合对性能要求较高或需要复杂切点匹配的场景如日志、监控等JDK动态代理和CGLIB动态代理的区别Spring AOP中的动态代理主要有两种方式JDK动态代理和CGLIB动态代理。SpringFramework 默认使用的动态代理是JDK动态代理 (由于后续版本已经整会了CGLB所以如果这个代理类没有实现接口会用 CGLIB)SpringBoot 2.x版本的默认动态代理是 CGLIBJDK动态代理如果目标类实现了接口Spring AOP会选择使用JDK动态代理目标类。代理类根据目标类实现的接口动态生成不需要自己编写生成的动态代理类和目标类都实现相同的接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。缺点目标类必须有实现的接口。如果某个类没有实现接口那么这个类就不能用JDK动态代理。CGLIB动态代理通过继承实现。如果目标类没有实现接口那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIBCode Generation Library可以在运行时动态生成类的字节码动态创建目标类的子类对象在子类对象中增强目标类。CGLIB是通过继承的方式做的动态代理因此如果某个类被标记为final那么它是无法使用CGLIB做动态代理的。优点目标类不需要实现特定的接口更加灵活。什么时候采用哪种动态代理如果目标对象实现了接口默认情况下会采用JDK的动态代理实现AOP如果目标对象实现了接口可以强制使用CGLIB实现AOP如果目标对象没有实现了接口必须采用CGLIB库两者的区别jdk动态代理使用jdk中的类Proxy来创建代理对象它使用反射技术来实现不需要导入其他依赖。cglib需要引入相关依赖asm.jar它使用字节码增强技术来实现。当目标类实现了接口的时候Spring Aop默认使用jdk动态代理方式来增强方法没有实现接口的时候使用cglib动态代理方式增强方法。AspectJ 定义的通知类型有哪些Before前置通知目标对象的方法调用之前触发After后置通知目标对象的方法调用之后触发AfterReturning返回通知目标对象的方法调用完成在返回结果值之后触发AfterThrowing异常通知目标对象的方法运行中抛出 / 触发异常后触发。AfterReturning 和 AfterThrowing 两者互斥。如果方法调用成功无异常则会有返回值如果方法抛出了异常则不会有返回值。Around环绕通知编程式控制目标对象的方法调用。环绕通知是所有通知类型中可操作范围最大的一种因为它可以直接拿到目标对象以及要执行的方法所以环绕通知可以任意的在目标对象的方法调用前后搞事甚至不调用目标对象的方法Spring AOP相关术语切面Aspect切面是通知和切点的结合。通知和切点共同定义了切面的全部内容。连接点Join point指方法在Spring AOP中一个连接点总是代表一个方法的执行。连接点是在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时、抛出异常时、甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程之中并添加新的行为。通知Advice在AOP术语中切面的工作被称为通知。切入点Pointcut切点的定义会匹配通知所要织入的一个或多个连接点。我们通常使用明确的类和方法名称或是利用正则表达式定义所匹配的类和方法名称来指定这些切点。引入Introduction引入允许我们向现有类添加新方法或属性。目标对象Target Object 被一个或者多个切面aspect所通知advise的对象。它通常是一个代理对象。织入Weaving织入是把切面应用到目标对象并创建新的代理对象的过程。在目标对象的生命周期里有以下时间点可以进行织入Spring通知有哪些类型在AOP术语中切面的工作被称为通知。通知实际上是程序运行时要通过Spring AOP框架来触发的代码段。Spring切面可以应用5种类型的通知前置通知Before在目标方法被调用之前调用通知功能后置通知After在目标方法完成之后调用通知此时不会关心方法的输出是什么返回通知After-returning 在目标方法成功执行之后调用通知异常通知After-throwing在目标方法抛出异常后调用通知环绕通知Around通知包裹了被通知的方法在被通知的方法调用之前和调用之后执行自定义的逻辑。多个切面的执行顺序如何控制5种类型的通知执行顺序正常执行前置---方法----返回---后置异常执行前置---方法----异常---后置同类型切面执行顺序通常使用Order注解直接定义切面顺序. 实现Ordered接口重写getOrder方法。什么情况下AOP会失效,怎么解决大部分失效是由于内部方法调用 如果在同一个类中的一个方法调用另一个方法AOP通知可能不会触发因为AOP通常是通过代理对象拦截外部方法调用的。解决方式是注入本类对象进行调用 或者设置暴露当前代理对象到本地线程 可以通过AopContext.currentProxy() 拿到当前正在调用的动态代理对象。静态方法 AOP通常无法拦截静态方法的调用因为静态方法不是通过对象调用的。解决方法是将静态方法调用替换为实例方法调用或者考虑其他技术来实现横切关注点。AOP配置问题 错误的AOP配置可能导致通知不正确地应用于目标方法或者在不希望的情况下应用。解决方法是仔细检查AOP配置确保切点表达式和通知类型正确配置。代理问题 如果代理对象不正确地创建或配置AOP通知可能无法生效。解决方法是调试底层源码确保代理对象正确创建并且AOP通知能够拦截代理对象的方法调用。说说你对 SpringMVC 的理解SpringMVC是一种基于 Java 的实现MVC设计模型的请求驱动类型的轻量级Web框架属于Spring框架的一个模块。它通过一套注解让一个简单的Java类成为处理请求的控制器而无须实现任何接口。同时它还支持RESTful编程风格的请求。Spring MVC 基于 servlet API 构建的可以说核心就是 DispatcherServlet即一个前端控制器。它通过注解、配置等方式将 HTTP 请求映射到控制器方法然后由控制器处理请求逻辑并将数据返回给视图层进行渲染。它的主要功能包括请求映射、数据绑定、视图解析、表单处理、异常处理等帮助我们快速构建 Web 应用。Spring 和 Spring MVC 的关系是什么?Spring 是基础Spring MVC 构建于 Spring 核心之上利用其提供的容器管理