Spring AOP 底层原理
aop 底层是采用动态代理机制实现的:接口+实现类
- 如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 JDK Proxy,去创建代理对象。
- 没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用Cglib 生成一个被代理对象的子类来作为代理。
就是由代理创建出一个和 impl 实现类平级的一个对象,但是这个对象不是一个真正的对象,只是一个代理对象,但它可以实现和 impl 相同的功能,这个就是 aop 的横向机制原理,这样就不需要修改源代码。
谈谈自己对于 Spring AOP 的了解?
AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
Spring Bean 容器的生命周期是什么样的?
- Bean 容器找到配置文件中 Spring Bean 的定义。
- Bean 容器利用 Java Reflection API 创建一个 Bean 的实例。
- 如果涉及到一些属性值 利用 set()方法设置一些属性值。
- 如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName()方法,传入 Bean 的名字。
- 如果 Bean 实现了 BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoader 对象的实例。
- 如果 Bean 实现了 BeanFactoryAware 接口,调用 setBeanFactory()方法,传入BeanFactory 对象的实例。
- 与上面的类似,如果实现了其他 *.Aware 接口,就调用相应的方法。
- 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessBeforeInitialization() 方法
- 如果 Bean 实现了 InitializingBean 接口,执行 afterPropertiesSet()方法。
- 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
- 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessAfterInitialization() 方法
- 当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法。
- 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。
介绍下 Spring Bean 都有哪些作用域 ?
- 单例 singleton : bean 在每个 Spring IOC 容器中只有一个实例。
- 原型 prototype:一个 bean 的定义可以有多个实例。
- request:每次 http 请求都会创建一个 bean。
- session:在一个 HTTP Session 中,一个 bean 定义对应一个实例。
- globalsession
- application
注解 @Autowired 和 @Resource 有什么区别?
- Resource 是 JDK 提供的,而 Autowired 是 Spring 提供的
- Resource 不允许找不到 bean 的情况,而 Autowired 允许(@Autowired(required = false))
- 指定 name 的方式不一样,@Resource(name = "baseDao"),@Autowired()@Qualifier("baseDao")
Resource 默认通过 name 查找,而 Autowired 默认通过 type 查找
(1)@Autowired 与@Resource 都可以用来装配 bean,都可以写在字段或 setter 方法上。
(2)@Autowired 默认按类型装配,默认情况下必须要求依赖对象存在,如果要允许 null值,可以设置它的 required 属性为 false。如果想使用名称装配可以结合@Qualifier 注解进行使用。
(3)@Resource,默认按照名称进行装配,名称可以通过 name 属性进行指定,如果没有指定 name 属性,当注解写在字段上时,默认取字段名进行名称查找。如果注解写在 setter方法上默认取属性名进行装配。当找不到与名称匹配的 bean 时才按照类型进行装配。但是需
要注意的是,如果 name 属性一旦指定,就只会按照名称进行装配。
Spring 框架事务注解用什么注解?使用该注解的失效场景?
@Transactional
- Transactional 注解应用在非 public 修饰的方法上@Transactional 注解属性propagation 设置错误
- @Transactional 注解属性 rollbackFor 设置错误
- 同一个类中方法调用,导致@Transactional 失效
- 异常被 catch“吃了”导致@Transactional 失效
自己写过 String 类能加载吗,之前的 String 是什么时候加载进去的?
不能加载,因为双亲委派机制,JVM 出于安全性的考虑,全限定类名相同的 String 是不能被加载的。
java.lang.String 会被顶级类加载器 Bootstrap Classloader 加载。当 class 文件被加载到内存中时,类文件常量池中的其他常量会加载到运行时常量池,但是字符串常量不会。它会首先在堆区中创建一个字符串对象,然后再把这个对象的引用保存到全局字符串常量池中。
介绍 Spring MVC 的工作流程 ?
- 用户向服务端发送一次请求,这个请求会先到前端控制器 DispatcherServlet。
- DispatcherServlet 接收到请求后会调用 HandlerMapping 处理器映射器。由此得知,该请求该由哪个 Controller 来处理(并未调用 Controller,只是得知)
- DispatcherServlet 调用 HandlerAdapter 处理器适配器,告诉处理器适配器应该要去执行哪个 Controller。
- HandlerAdapter 处理器适配器去执行 Controller 并得到 ModelAndView(数据和视图),并层层返回给 DispatcherServlet。
- DispatcherServlet 将 ModelAndView 交给 ViewReslover 视图解析器解析,然后返回真正的视图。
- DispatcherServlet 将模型数据填充到视图中
- DispatcherServlet 将结果响应给用户
Spring 框架中用到了哪些设计模式?
- 工厂设计模式 : Spring 使用工厂模式通过 BeanFactory、ApplicationContext 创建bean 对象。
- 代理设计模式 : Spring AOP 功能的实现。
- 单例设计模式 : Spring 中的 Bean 默认都是单例的。
- 模板方法模式 : Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。
- 包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
- 观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。
- 适配器模式 : Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配 Controller。
什么是 Spring Boot?
多年来,随着新功能的增加,spring 变得越来越复杂。访问 spring 官网页面,我们就会看到可以在我们的应用程序中使用的所有 Spring 项目的不同功能。如果必须启动一个新的Spring 项目,我们必须添加构建路径或添加 Maven 依赖关系,配置应用程序服务器,添加spring 配置。因此,开始一个新的 spring 项目需要很多努力,因为我们现在必须从头开始做所有事情。
Spring Boot 是解决这个问题的方法。
Spring Boot 已经建立在现有 spring 框架之上。使用 spring 启动,我们避免了之前我们必须做的所有样板代码和配置。因此,Spring Boot 可以帮助我们以最少的工作量,更加健壮地使用现有的 Spring 功能。
Spring Boot 有哪些优点?
Spring Boot 的优点有:
- 减少开发,测试时间和努力。
- 使用 JavaConfig 有助于避免使用 XML。
- 避免大量的 Maven 导入和各种版本冲突。
- 提供意见发展方法。
- 通过提供默认值快速开始开发。
- 没有单独的 Web 服务器需要。这意味着你不再需要启动 Tomcat,Glassfish 或其他任何东西。
- 需要更少的配置 因为没有 web.xml 文件。只需添加用@ Configuration 注释的类,然后添加用@Bean 注释的方法,Spring 将自动加载对象并像以前一样对其进行管理。您甚至可以将@Autowired 添加到 bean 方法中,以使 Spring 自动装入需要的依赖关系中。
- 基于环境的配置 使用这些属性,您可以将您正在使用的环境传递到应用程序:-Dspring.profiles.active = {enviornment}。在加载主应用程序属性文件后,Spring 将在(application{environment} .properties)中加载后续的应用程序属性文件。
什么是 Spring Cloud?
Spring cloud 流应用程序启动器是基于 Spring Boot 的 Spring 集成应用程序,提供与外部系统的集成。Spring cloud Task,一个生命周期短暂的微服务框架,用于快速构建执行有限数据处理的应用程序。
使用 Spring Boot 开发分布式微服务时,我们需要关注哪些问题?
- 与分布式系统相关的复杂性-这种开销包括网络问题,延迟开销,带宽问题,安全问题。
- 服务发现-服务发现工具管理群集中的流程和服务如何查找和互相交谈。它涉及一个服务目录,在该目录中注册服务,然后能够查找并连接到该目录中的服务。
- 冗余-分布式系统中的冗余问题。
- 负载平衡 --负载平衡改善跨多个计算资源的工作负荷,诸如计算机,计算机集群,网络链路,中央处理单元,或磁盘驱动器的分布。
- 性能-问题 由于各种运营开销导致的性能问题。
- 部署复杂性-Devops 技能的要求。
服务注册和发现是什么意思?Spring Cloud 如何实现?
当我们开始一个项目时,我们通常在属性文件中进行所有的配置。随着越来越多的服务开发和部署,添加和修改这些属性变得更加复杂。有些服务可能会下降,而某些位置可能会发生变化。手动更改属性可能会产生问题。
Eureka 服务注册和发现可以在这种情况下提供帮助。由于所有服务都在 Eureka 服务器上注册并通过调用 Eureka 服务器完成查找,因此无需处理服务地点的任何更改和处理。
Spring Cloud 断路器的作用
当一个服务调用另一个服务由于网络原因或自身原因出现问题,调用者就会等待被调用者的响应 当更多的服务请求到这些资源导致更多的请求等待,发生连锁效应(雪崩效应)。
断路器有完全打开状态:一段时间内达到一定的次数无法调用,并且多次监测没有恢复的迹象,断路器完全打开,那么下次请求就不会请求到该服务。
半开:短时间内有恢复迹象,断路器会将部分请求发给该服务,正常调用时 断路器关闭。
关闭:当服务一直处于正常状态,能正常调用
Dubbo 和 Spring Cloud 有什么关系?
Dubbo 是 SOA 时代的产物,它的关注点主要在于服务的调用,流量分发、流量监控和熔断。而 Spring Cloud 诞生于微服务架构时代,考虑的是微服务治理的方方面面,另外由于依托了 Spring、Spring Boot 的优势之上,两个框架在开始目标就不一致,Dubbo 定位服务治理、Spring Cloud 是打造一个生态。
Dubbo 和 Spring Cloud 有什么哪些区别?
- Dubbo 底层是使用 Netty 这样的 NIO 框架,是基于 TCP 协议传输的,配合以 Hession 序列化完成 RPC 通信。
- Spring Cloud 是基于 Http 协议 Rest 接口调用远程过程的通信,相对来说 Http 请求会有更大的报文,占的带宽也会更多。但是 REST 相比 RPC 更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这在强调快速演化的微服务环境下,显得更为合适,至于注重通信速度还是方便灵活性,具体情况具体考虑。
不同版本的 Spring Framework 有哪些主要功能?
Version | Feature |
---|---|
Spring 2.5 | 发布于 2007 年。这是第一个支持注解的版本。 |
Spring 3.0 | 发布于2009年:它完全利用了 JavaS 中的改进,并为 JEE6 提供了支持。 |
Spring 4.0 | 发布于 2013 年。这里第一个完全变持 JAMA8 的版本。 |
什么是 Spring Framework?
Spring 是一个开源应用框架,旨在降低应用程序开发的复杂度。它是轻量级、松散耦合的。
它具有分层体系结构,允许用户选择组件,同时还为 J2EE 应用程序开发提供了一个有凝聚力的框架。它可以集成其他框架,如 Structs、Hibernate、EJB 等,所以又称为框架的框架。
列举 Spring Framework 的优点。
由于Spring Frameworks的分层架构,用户可以自由选择自己需要的组件。
Spring Framework 支持 POJO(Plain Old Java Object) 编程,从而具备持续集成和可测试性。
由于 依赖注入和控制反转,JDBC 得以简化。它是开源免费的。
Spring Framework 有哪些不同的功能?
- 轻量级 - Spring 在代码量和透明度方面都很轻便。
- IOC - 控制反转
- AOP - 面向切面编程 可以将应用业务逻辑和系统服务分离,以实现高内聚。
- 容器 - Spring 负责创建和管理对象(Bean)的生命周期和配置。
- MVC - 对 web 应用提供了高度可配置性,其他框架的集成也十分方便。
- 事务管理 - 提供了用于事务管理的通用抽象层。Spring 的事务支持也可用于 容器较少的环境。
- JDBC 异常 - Spring 的 JDBC 抽象层提供了一个异常层次结构,简化了 错误处理策略。
Spring Framework 中有多少个模块,它们分别是什么?
Spring 核心容器 – 该层基本上是 Spring Framework 的核心。它包含以下模块:
- Spring Core
- Spring Bean
- SpEL (Spring Expression Language)
- Spring Context数据访问/集成 – 该层提供与数据库交互的支持。
它包含以下模块:
- JDBC (Java DataBase Connectivity)
- ORM (Object Relational Mapping)
- OXM (Object XML Mappers) · JMS (Java Messaging Service)
- Transaction
Web – 该层提供了创建 Web 应用程序的支持。它包含以下模块:
- Web
- Web – Servlet
- Web – Socket
- Web – Portlet
AOP
- 该层支持面向切面编程
Instrumentatio
- 该层为类检测和类加载器实现提供支持。
Test
- 该层为使用 JUnit 和 TestNG 进行测试提供支持。
几个杂项模块:
- Messaging – 该模块为 STOMP 提供支持。它还支持注解编程模型,该模型用于从 WebSocket 客户端路由和处理 STOMP 消息。
- Aspects – 该模块为与 AspectJ 的 集成提供支持。
什么是 Spring 配置文件?
Spring 配置文件是 XML 文件。该文件主要包含类信息。它描述了这些类是如何配置以及相互引入的。但是,XML 配置文件冗长且更加干净。如果没有正确规划和编写,那么在大项 目中管理变得非常困难。
Spring 应用程序有哪些不同组件?
- Spring 应用一般有以下组件:
- 接口 - 定义功能。
- Bean 类 - 它包含属性,setter 和 getter 方法,函数等。 · Spring 面向切面编程(AOP) - 提供面向切面编程的功能。 · Bean 配置文件 - 包含类的信息以及如何配置它们。
- 用户程序 - 它使用接口。
使用 Spring 有哪些方式?使用 Spring 有以下方式:
- 作为一个成熟的 Spring Web 应用程序。
- 作为第三方 Web 框架,使用 Spring Frameworks 中间层。 · 用于远程使用。
- 作为企业级 Java Bean,它可以包装现有的 POJO(Plain Old JavaObjects)。
什么是 Spring IOC 容器?
Spring 框架的核心是 Spring 容器。容器创建对象,将它们装配在一起,配置它们并管理它们的完整生命周期。Spring 容器使用依赖注入来管理组成应用程序的组件。容器通过读取提供的配置元数据来接收对象进行实例化,配置和组装的指令。该元数据可以通过 XML,Java注解或 Java 代码提供。
什么是依赖注入?
在依赖注入中,您不必创建对象,但必须描述如何创建它们。您不是直接在代码 中将组件 和服务连接在一起,而是描述配置文件中哪些组件需要哪些服务。由 IoC 容器将它们装配在一起。
可以通过多少种方式完成依赖注入?
通常,依赖注入可以通过三种方式完成,即:
- 构造函数注入
- setter 注入
- 接口注入 在 Spring Framework 中,仅使用构造函数和 setter 注入
区分构造函数注入和 setter 注入
Spring 中有多少种 IOC 容器?
BeanFactory - BeanFactory 就像一个包含 bean 集合的工厂类。它会在客户端要求时实例化bean。
ApplicationContext - ApplicationContext 接口扩展了 BeanFactory 接口。它在BeanFactory 基础上提供了一些额外的功能。
区分 BeanFactory 和 ApplicationContext。
列举 IoC 的一些好处
IoC 的一些好处是:
- 它将最小化应用程序中的代码量。
- 它将使您的应用程序易于测试, 因为它不需要单元测试用例中的任何单例或 JNDI 查找机制。
- 它以最小的影响和最少的 侵入机制促进松耦合。
- 它支持即时的实例化和延迟加载服务。
Spring IoC 的实现机制。
Spring 中的 IoC 的实现原理就是工厂模式加反射机制。 示例:
interface Fruit {
public abstract void eat();
}
class Apple implements Fruit {
public void eat(){
System.out.println("Apple");
}
}
class Orange implements Fruit {
public void eat(){
System.out.println("Orange");
}
}
class Factory {
public static Fruit getInstance(String ClassName) {
Fruit f=null;
try {
f=(Fruit)Class.forName(ClassName).newInstance();
}
catch (Exception e) {
e.printStackTrace();
}
return f;
}
}
class Client {
public static void main(String[] a) {
Fruit f=Factory.getInstance("io.github.dunwu.spring.Apple");if(f!=null){
f.eat();
}
}
什么是 Spring Bean?
- 它们是构成用户应用程序主干的对象。
- Bean 由 Spring IoC 容器管理。
- 它们由 Spring IoC 容 器实例化,配置,装配和管理。
- Bean 是 基于用户提供给容器的配置元数据创建。
Spring 提供了哪些配置方式?
基于 xml 配置 bean 所需的依赖项和服务在 XML 格式的配置文件中指定。这些配置文件 通常
包含许多 bean 定义和特定于应用程序的配置选项。它们通常以 bean 标签开头。例如:
<bean id="studentbean" class="org.edureka.firstSpring.StudentBean">
<property name="name" value="Edureka"></property>
</bean>
基于注解配置 您可以通过在相关的类,方法或字段声明上使用注解,将 bean 配置为组件 类本身,而不是使用 XML 来描述 bean 装配。默认情况下,Spring 容器中未打开注解装配。因此,您需要在使用它之前在 Spring 配置文件中启用它。例如:
<beans>
<context:annotation-config/>
<!-- bean definitions go here -->
</beans>
基于 Java API 配置
Spring 的 Java 配置是通过使用 @Bean 和 @Configuration 来实现。
(1) @Bean 注解 扮演与 <bean/>
元素相同的角色。
(2) @Configuration 类允许通过简单地调用同一个 类中的其他 @Bean 方法来定义 bean 间依赖关系。 例如:
@Configuration
public class StudentConfig {
@Bean
public StudentBean myStudent() {
return new StudentBean();
}
}
Spring 支持几种 bean scope?
Spring bean 支持5种 scope :
-
Singleton:在整个应用程序中只会创建一个 bean 实例,无论被明多少次。默认采用该 scope。
-
Prototype:每次请求该 bean 时都会创建一个新的实例。
-
Request:在一次 HTTP 请求中,每个 bean 实例都将存在。例如,对于同一个 HTTP 请求,两个不同的 bean 定义将分别创建两个不同的 bean 实例。
-
Session:在同一个 HTTP Session 中,每个 bean 实例都将存在。
-
Global Session:在一个全局的 HTTP Session 中,每个 bean 实例将只存在一个。仅适用于使用 Portlet 上下文时,它是 PortletContext 的特定作用域。