目录
5.@Component和@Controller和@Repository和@Service有什么区别
1.什么是IOC、DI
控制反转(IOC)是一种设计思想,就是原本在程序中需要手动创建对象,现在交由Spring管理创建。比如说,原本我们要在A类中调用B类的方法,就要直接在A中new出B类对象,然后调用B类中的方法,虽然能实现效果,不过存在一个问题,更改需求会对源代码进行修改,这不是好的解决方法。现在创建B对象就交给了Spring,在Spring中,B类对象被看成Bean对象(Spring中类就是Bean),这个Bean对象由spring容器进行创建和管理,这样的话A对象获取B对象中的方法,由主动new,变成被动等Spring创建。主动变被动,就可以理解成控制反转,这样大大降低了耦合,Spring中全都用这种思想,即依赖类不由程序员实例化,而是通过Spring容器帮我们new指定的实例并且将实例注入到需要该对象的类中,而 依赖注入(DI) 是实现这种思想的具体手段,Spring通过DI(依赖注入)实现IOC(控制反转)。
2.什么是AOP
面向切片编程(AOP—Aspect Oriented Programming)可以说是对OOP(面向对象编程)的补充和完善,面向对象就是将事物的特性和行为抽象为一个对象,如people类有身高、体重、年龄等属性,也有吃饭、睡觉等行为。把这些特性和行为封装成一个类,然后可以统一调用。面向切片也可以,比如people类有自己的属性和行为,但是有小一部分人生病要去医院看病,看病这个业务逻辑就不属于哪一个类,因为people泛指所有人,所有人不会都看病。AOP就是把医院看病这一个业务逻辑功能抽取出来,然后动态把这个功能切入到需要的方法(或行为)中,需要的才切入,这样便于减少系统的重复代码,降低模块间的耦合度。常用到AOP的就是安全校验、日志操作、事务操作等,给你先定义好,然后在想用的地方用,这样不会影响已经在服务器运行的项目,然后又能注入新功能,灵活。我们开发dao->service->controller是纵向的,这个AOP就是横向切入,如横向切入一个日志Log,打印执行过程。
3.spring框架的作用
Spring 框架是一个开源的 Java 应用框架,主要作用是简化企业级应用程序的开发。它通过提供 IOC(控制反转)和 AOP(面向切面编程)等核心特性,帮助开发者轻松管理对象的创建与依赖关系,支持声明式事务管理、数据访问、消息传递、以及集成各种其他技术框架,使得开发效率更高、代码更易于维护。
4.spring的常用注解
1. @Component
- 作用:标记一个类为 Spring 管理的组件,Spring 容器会把这个类创建成一个 Bean。
- 通俗理解:相当于告诉 Spring "请把这个类交给你管理,并帮我创建它的对象"。
2. @Controller
- 作用:用于定义控制器类,处理来自 Web 客户端的请求,返回页面视图。
- 通俗理解:它是专门用来处理网页请求的,可以把网页请求(如点击按钮)交给它处理。
3. @Service
- 作用:标记服务层的类,表示这个类用来写业务逻辑。
- 通俗理解:类似业务经理,处理具体的业务需求。
4. @Repository
- 作用:标记数据访问层的类,主要用来与数据库打交道。
- 通俗理解:相当于数据库的助手,专门负责存取数据。
5. @Autowired
- 作用:自动把需要的依赖对象注入进来。
- 通俗理解:假设你需要一把锤子,
@Autowired
就会自动找到锤子并交给你使用,而你不需要自己去找。
6. @Configuration
- 作用:表示当前类是一个配置类,类似于传统 XML 配置文件。
- 通俗理解:相当于告诉 Spring "这个类里是我定义的一些配置信息"。
7. @Bean
- 作用:用于定义一个 Spring Bean,通常放在
@Configuration
类中。 - 通俗理解:告诉 Spring "我要创建这个对象,并把它注册成 Bean,让它在容器里可用"。
8. @RequestMapping
- 作用:用于映射 HTTP 请求到控制器的方法上,通常用于处理网页的 URL 请求。
- 通俗理解:就像一个门牌号,指引用户访问特定的功能。例如,访问
/home
就会触发相应的控制器方法。
9. @GetMapping
和 @PostMapping
- 作用:简化
@RequestMapping
,分别用来处理 GET 和 POST 请求。 - 通俗理解:
@GetMapping
是处理查询信息的请求。@PostMapping
是处理提交数据的请求。
10. @RequestParam
- 作用:绑定 URL 请求中的参数到控制器方法的参数。
- 通俗理解:假如用户在网址里输入
?name=Tom
,@RequestParam("name")
就会把Tom
传递到你方法的参数中。
11. @PathVariable
- 作用:把 URL 路径中的某部分参数绑定到方法的参数上。
- 通俗理解:比如
url: /user/123
,@PathVariable("id")
就会把123
作为方法的参数使用。
12. @RestController
- 作用:组合了
@Controller
和@ResponseBody
,返回 JSON 格式的数据,而不是页面视图。 - 通俗理解:它是专门用来处理 API 请求的,直接返回数据,不会渲染页面。
13. @ResponseBody
- 作用:告诉 Spring 返回的数据不是页面,而是直接写入 HTTP 响应体(通常是 JSON)。
- 通俗理解:相当于告诉 Spring "不用找页面了,直接把数据传回给客户端"
5.@Component和@Controller和@Repository和@Service有什么区别
1. @Component
- 作用:最基础的注解,表示一个通用的组件,告诉 Spring 把这个类交给它来管理。
- 通俗理解:
@Component
就像一个“万能标记”,可以用在任何类上。它是一个泛用的注解,其他三个注解其实都是从@Component
扩展出来的,专门针对不同的应用场景。
2. @Controller
- 作用:专门用于标识控制层(也叫 Web 层)的类,处理客户端的请求并返回视图或数据。
- 通俗理解:这是
@Component
的特殊化,专门负责处理网页请求和响应。你可以理解为这是一个专门用来跟用户打交道的“接待员”,用户点击网页时会触发@Controller
里的方法。
3. @Service
- 作用:用于标记服务层(业务逻辑层)的类,处理应用的核心业务逻辑。
- 通俗理解:
@Service
也是@Component
的扩展,专门用于业务逻辑处理。你可以理解为“业务经理”,它负责拿到用户的需求(请求),然后执行具体的业务操作,比如计算、处理数据等。
4. @Repository
- 作用:用于标记数据访问层(DAO)的类,专门负责与数据库交互。
- 通俗理解:这是
@Component
的另一个扩展,专门负责数据库操作。你可以把它想象成一个“数据助手”,专门帮助你存储、读取和更新数据库里的数据。
6.@Autowired和Resource两个注解的区别
1)@Autowired是spring框架提供的注解,而@Resource是JDK提供的注解。
2)@Autowired默认是按照类型注入,而@Resource默认是按照名称注入。
3)@Autowired可以用于字段、构造方法和方法上,@Resource可以用于字段和set方法上
4)@Autowired在有多个相同类型的bean时,需要结合@Qualifier注解来精确注入,@Resource在有多个相同类型的bean时,会根据名称进行匹配,如果找不到对应的bean则会报错。
7.bean的生命周期
-
实例化(Instantiation)
- 过程:Spring 通过反射机制创建 Bean 的实例。这一步相当于用
new
关键字创建对象。 - 通俗理解:就像在工厂里,先造出一个“空”的对象,还没有组装任何具体内容。
- 过程:Spring 通过反射机制创建 Bean 的实例。这一步相当于用
-
属性填充(Populate Properties)
- 过程:Spring 根据配置文件或注解,把需要的依赖注入到 Bean 中(例如
@Autowired
)。 - 通俗理解:给新造的对象“安装”上各种零件,比如依赖的其他对象、属性值等。
- 过程:Spring 根据配置文件或注解,把需要的依赖注入到 Bean 中(例如
-
调用
BeanNameAware
接口的setBeanName
方法- 过程:如果 Bean 实现了
BeanNameAware
接口,Spring 会调用它的setBeanName
方法,传递当前 Bean 的名字。 - 通俗理解:告诉对象它的名字,相当于给它贴上一个名字标签。
- 过程:如果 Bean 实现了
-
调用
BeanFactoryAware
、ApplicationContextAware
等接口的方法- 过程:如果 Bean 实现了这些接口,Spring 会把相应的 BeanFactory 或 ApplicationContext 传递给它。
- 通俗理解:对象被告知它所在的“环境”或“上下文”,方便它了解自己所在的位置和可以用的资源。
-
BeanPostProcessor
的postProcessBeforeInitialization
方法- 过程:在 Bean 初始化之前,Spring 会调用所有注册的
BeanPostProcessor
的postProcessBeforeInitialization
方法。 - 通俗理解:对象初始化前的“预处理”,可以对对象进行某些“特殊操作”。
- 过程:在 Bean 初始化之前,Spring 会调用所有注册的
-
初始化(Initialization)
- 过程:如果 Bean 实现了
InitializingBean
接口,则会调用它的afterPropertiesSet
方法。或者,如果在配置文件中指定了init-method
,也会调用该方法。 - 通俗理解:对象的“自检”或“启动”过程,让它做好准备,开始运行。
- 过程:如果 Bean 实现了
-
BeanPostProcessor
的postProcessAfterInitialization
方法- 过程:在 Bean 初始化之后,Spring 会再次调用
BeanPostProcessor
的postProcessAfterInitialization
方法。 - 通俗理解:对象初始化后的“后处理”,这是它准备好后最后的检查或调整。
- 过程:在 Bean 初始化之后,Spring 会再次调用
-
Bean 就绪(Ready to Use)
- 过程:Bean 现在完全初始化好了,可以被应用程序使用。
- 通俗理解:对象已经完全组装好,可以开始正常工作了。
-
销毁(Destruction)
- 过程:当 Spring 容器关闭时,如果 Bean 实现了
DisposableBean
接口,会调用它的destroy
方法。或者,如果在配置文件中指定了destroy-method
,也会调用这个方法。 - 通俗理解:对象的“清理”过程,释放资源、保存状态、关闭连接等。
- 过程:当 Spring 容器关闭时,如果 Bean 实现了
8.spring事务的实现方式
Spring 提供了两种主要的事务管理方式:编程式事务管理 和 声明式事务管理。
1. 编程式事务管理
-
解释:编程式事务管理是指在代码中通过显式的方式来管理事务的生命周期。你需要在代码里手动定义事务的开始、提交和回滚。它的优势是灵活,可以精确控制事务的边界,但缺点是代码会变得冗长复杂,增加了维护成本。
-
适用场景:这种方式通常适用于需要非常细粒度的事务控制,或者是在少数情况下需要程序逻辑特别复杂的场景。
2. 声明式事务管理
-
解释:声明式事务管理是 Spring 中最常用的事务管理方式。通过配置(例如注解或 XML 配置),你可以声明哪些方法或类需要事务支持。Spring 会自动处理这些事务的开始、提交和回滚,基于 AOP(面向切面编程)机制。
-
优点:声明式事务管理不需要在代码中手动管理事务,简化了代码,并且更容易维护。开发者只需关注业务逻辑本身,Spring 框架会自动处理事务相关的细节。
-
适用场景:适合大多数业务场景,特别是当事务逻辑比较简单或典型时,比如常规的数据库操作(增、删、改)。
9.spring事务的失效场景
1. 事务方法是 private
或 final或者
事务注解 @Transactional
没有被应用在 public
方法上
Spring 声明式事务基于 AOP(面向切面编程)实现,AOP 通过代理对象来处理事务。如果方法是 private
或 final
,Spring 无法代理这些方法,从而导致事务失效。
-
原因:Spring AOP 需要通过代理类调用目标对象的方法。如果是
private
方法,Spring 无法从代理类外部访问它;如果是final
方法,代理类无法重写它,从而不能应用事务。 -
解决方案:将方法的访问修饰符改为
public
或protected
,并避免将事务方法声明为final
。
2. 事务方法内部调用(self-invocation)
如果一个类中的方法 A 调用了同一类中的另一个带有 @Transactional
的方法 B,由于调用是内部的,Spring AOP 不会生成代理对象,因此事务不会生效。
-
原因:Spring AOP 是通过代理来管理事务的,代理只能拦截外部的调用。如果是类内部的自我调用,代理不会被使用,事务拦截器也无法生效。
-
解决方案:将事务方法放到另一个类中,或者使用 AspectJ 这种基于字节码增强的 AOP 来替代 Spring AOP。
3. 事务方法抛出的异常不是 RuntimeException
默认情况下,Spring 只在捕获到 RuntimeException
或 Error
时才会触发事务回滚。如果事务方法抛出的异常是 CheckedException
,则不会回滚。
-
原因:Spring 的事务管理默认遵循
unchecked exceptions
(如RuntimeException
)导致回滚,而checked exceptions
(如Exception
)默认不会导致回滚。 -
解决方案:
- 可以在
@Transactional
注解中配置rollbackFor
来指定哪些checked exceptions
也会触发回滚。 - 示例:
@Transactional(rollbackFor = Exception.class)
- 可以在
4. 代理模式导致的失效(CGLIB 和 JDK 动态代理)
Spring 使用两种代理方式:JDK 动态代理和 CGLIB。JDK 动态代理只代理接口,如果你的类没有实现接口,Spring 会使用 CGLIB 代理类。如果在项目中使用的代理模式不匹配,事务可能不会生效。
- 原因:如果你的类没有实现接口,但你使用了 JDK 代理,事务可能不会生效。
- 解决方案:确保类实现了接口(如果使用 JDK 动态代理),或者强制使用 CGLIB 代理(通过配置
proxyTargetClass = true
)。
10.spring事务的传播特性
1. PROPAGATION_REQUIRED (默认)
- 含义:如果当前已经存在一个事务,方法将在当前事务中运行。如果当前没有事务,Spring 将创建一个新的事务。
- 应用场景:这是最常见的传播行为,适用于大多数场景。它确保所有调用都在同一个事务中执行,具有原子性。
2. PROPAGATION_REQUIRES_NEW
- 含义:无论当前是否有事务,Spring 都会创建一个新的事务。如果当前存在事务,Spring 会将该事务挂起,直到新事务完成。
- 应用场景:适用于需要强制隔离的操作,特别是当你不希望被外部事务影响时。例如,你可以在一个事务中记录日志操作,并且不希望日志操作回滚,即使主事务失败。
3. PROPAGATION_SUPPORTS
- 含义:如果当前有事务,方法就在事务中执行。如果当前没有事务,方法则以非事务方式执行。
- 应用场景:适用于对事务要求不严格的场景,如一些读取操作。在有事务时参与事务,没有事务时正常执行。
4. PROPAGATION_NOT_SUPPORTED
- 含义:方法不应该在事务中执行。如果当前存在事务,Spring 会将当前事务挂起,方法将以非事务方式运行。
- 应用场景:适用于不需要事务且不希望事务管理带来开销的场景,例如读取大数据集时,或者性能敏感的操作。
5. PROPAGATION_NEVER
- 含义:方法不应该在事务中执行。如果当前存在事务,Spring 将抛出异常。
- 应用场景:适用于明确不允许在事务中运行的场景。例如,在某些需要明确禁止事务的业务逻辑中使用。
6. PROPAGATION_MANDATORY
- 含义:方法必须在事务中运行。如果当前没有事务,Spring 将抛出异常。
- 应用场景:适用于必须在事务中运行的场景,但不能自行启动事务。例如,要求所有的数据库操作都必须由调用者提供的事务管理。
11.springboot怎么实现定时任务
启用定时任务
-
启用定时任务:在主程序类或配置类中,通过添加
@EnableScheduling
注解来启用定时任务功能。 -
使用
@Scheduled
注解:将@Scheduled
注解加到需要执行定时任务的方法上。它支持以下几种常见的使用方式:- fixedRate:按照固定的频率执行任务,不论上一个任务是否完成。例如,每5秒执行一次。
- fixedDelay:在上一个任务完成后,等待固定时间再执行下一个任务。例如,任务完成后等待5秒再执行。
- cron:通过
cron
表达式来控制任务执行的时间。它可以精确到秒、分钟、小时、天等,非常灵活。
12.springboot需要独立的容器运行吗
Spring Boot 不需要独立的容器来运行。它可以直接通过内嵌的 Web 服务器(如 Tomcat、Jetty 或 Undertow)在 Java 应用程序内部运行。这意味着 Spring Boot 应用是自包含的,可以像普通的 Java 应用程序一样运行,而不需要在外部的应用服务器或容器中部署。
Spring Boot 的默认行为是打包成可执行的 JAR 文件,其中包含内嵌的 Web 服务器。你只需运行 JAR 文件即可启动应用,无需提前配置和部署应用服务器。
如果有需要,Spring Boot 也可以打包为 WAR 文件并部署到传统的 Web 容器中。
13.@Import注解的理解
@Import
注解在 Spring 中用于将其他配置类或组件引入到当前的应用程序中,简化了配置管理。它的主要作用是帮助开发者将多个配置类或组件集中管理,便于模块化开发。当你有很多配置文件时,可以用 @Import
把它们组合在一起。
14.@Import注解与其他注解的区别
1. @Import
vs @ComponentScan
-
@Import
:手动指定需要导入的配置类或组件类,将其直接加载到 Spring 容器中。适合在明确知道某些类时使用,可以一次导入多个类或配置文件。- 作用:引入其他配置类、普通类,或动态地根据条件加载特定类。
- 使用场景:在有多个分散的配置文件或类时,将它们整合到主配置中。
-
@ComponentScan
:自动扫描指定包及其子包下的类,并将标注了@Component
、@Service
、@Controller
等注解的类自动注册为 Spring Bean。- 作用:通过包路径自动发现并注册 Spring 组件。
- 使用场景:适合项目中需要自动发现和加载 Bean 的情况,不需要手动指定每个类。
区别:
@Import
是手动指定要引入的类或配置,而@ComponentScan
是自动扫描某个包路径下的类。
2. @Import
vs @Autowired
-
@Import
:用于将其他类或配置类导入到 Spring 容器中,让 Spring 容器管理这些类,通常用于模块化或跨配置文件引用类。- 使用场景:当需要加载整个配置类或多个组件时。
-
@Autowired
:用于自动注入依赖对象,将一个类的实例自动注入到另一个类中,解决类与类之间的依赖关系。- 使用场景:用于解决具体类的依赖,如在一个类中需要另一个类的实例时。
区别:
@Import
处理的是类或配置的引入,@Autowired
处理的是对象的依赖注入。
3. @Import
vs @Bean
-
@Import
:可以导入多个配置类或普通类到 Spring 容器中,并让 Spring 管理它们。- 使用场景:当你需要批量或集中管理类和配置时。
-
@Bean
:用于在配置类中定义一个单独的 Bean,告诉 Spring 容器手动管理这个 Bean 的创建。每个@Bean
方法定义一个 Spring 管理的对象。- 使用场景:用于定义单个对象实例。
区别:
@Import
是批量引入类,@Bean
是定义单个 Bean 对象。
4. @Import
vs @Configuration
-
@Import
:用于引入其他配置类,确保这些类的 Bean 被加载到 Spring 容器中。- 使用场景:用来整合和加载多个配置类。
-
@Configuration
:声明一个类是配置类,用于定义 Bean。@Configuration
类本身是通过@Import
来集成到应用中的。- 使用场景:定义 Bean 配置的地方。
区别:
@Configuration
声明类为配置类,@Import
则用于加载这些配置类