IOC
springboot自动创建对象,并存起来
Inversion of Control控制反转
对象的创建权限交给Spring,并把创建好的对象存到容器里(其实就是一个map集合)
DI
Dependency Injection
自动注入放到IOC容器中的对象
实际就是给属性自动赋值
Bean对象
存到IOC容器里的对象都叫Spring Bean对象
使用IOC和DI时,
Bean对象的创建和获取都和IOC容器有关
Bean对象之间搭配使用
哪些类适合控制反转和依赖注入?
控制器类(Controller)-
Spring MVC是Spring框架的一部分,它提供了一个基于模型-视图-控制器(MVC)的Web应用程序开发架构。在Spring MVC中,控制器类负责处理客户端请求并返回响应。通过将控制器类交给Spring管理,可以方便地实现请求的映射、参数绑定、异常处理等功能。
服务类(Service)
在应用程序中,服务类负责处理业务逻辑。将服务类交给Spring管理可以实现依赖注入、事务管理等功能。使用Spring的依赖注入功能,可以方便地将依赖的类注入到服务类中,从而实现松耦合和可测试性。同时,Spring的事务管理功能可以确保服务类中的数据库操作具有一致性和完整性。
数据访问对象(DAO)
DAO类负责处理数据库的操作。通过将DAO类交给Spring管理,可以方便地使用Spring的事务管理功能和持久化框架(如Hibernate或MyBatis)来简化数据库操作。此外,Spring还提供了一些便捷的功能,如异常转换和批量更新,用于简化数据库访问的代码
工具类
工具类通常包含一些辅助方法,用于完成特定的功能。通过将工具类交给Spring管理,可以方便地在其他类中使用这些方法,避免手动创建对象。
AOP切面(Aspect)
DAO类负责处理数据库的操作。通过将DAO类交给Spring管理,可以方便地使用Spring的事务管理功能和持久化框架(如Hibernate或MyBatis)来简化数据库操作。此外,Spring还提供了一些便捷的功能,如异常转换和批量更新,用于简化数据库访问的代码
配置类(Configuration)
DAO类负责处理数据库的操作。通过将DAO类交给Spring管理,可以方便地使用Spring的事务管理功能和持久化框架(如Hibernate或MyBatis)来简化数据库操作。此外,Spring还提供了一些便捷的功能,如异常转换和批量更新,用于简化数据库访问的代码
如何在Spring中使用控制反转和依赖注入?
1.控制反转注解
@Component
普通类上加上该注解即可实现IOC
组合特化注解
@Controller
@RestController
@Service
@Mapper
@Repository
2.依赖注入注解
依赖注入注解
@Resource 属性注入优先使用@Resource(默认按照Bean名字从容器中获取,默认的springBean名字时类对应的小驼峰)
默认Bean名字注入
@Autowired
默认Bean类型注入
@Primary(解决Bean重名问题)
指定注入Bean优先级
@Qualifier(解决Bean重名问题)
指定Bean的名字
3.组合注解@SpringBootApplication
面试题
1.说说SpringBoot加载启动流程
1. 入口类
启动类通常是用
@SpringBootApplication
注解的类。这个注解结合了@Configuration
、@EnableAutoConfiguration
和@ComponentScan
三个注解。通过
public static void main(String[] args)
方法调用SpringApplication.run()
启动应用。2. 创建 SpringApplication 实例
SpringApplication
是 Spring Boot 应用的核心类。调用run()
方法时,它会创建一个ApplicationContext
实例。3. 准备环境
在创建
ApplicationContext
之前,Spring Boot 会准备应用环境(Environment
),比如读取配置文件(application.properties
或application.yml
)和命令行参数。4. 创建 ApplicationContext
Spring Boot 默认使用
AnnotationConfigApplicationContext
或WebApplicationContext
(对于 Web 应用),并根据配置创建适当的上下文。5. 自动配置
启用自动配置机制。
@EnableAutoConfiguration
会根据类路径中的库自动配置 Spring 应用的各个部分(如数据源、Spring MVC、缓存等)。Spring Boot 使用
spring.factories
文件来加载自动配置类。6. Bean 创建和初始化
扫描组件并创建 Bean。
@ComponentScan
注解会扫描指定包及其子包中的组件(如@Service
、@Repository
、@Controller
等)。在此过程中,所有的 Bean 会被创建并初始化,包括执行
@PostConstruct
注解的方法。7. 加载 ApplicationRunner 和 CommandLineRunner
在上下文初始化完成后,Spring Boot 会执行所有实现了
ApplicationRunner
和CommandLineRunner
接口的 Bean,以便在应用启动后执行一些逻辑。8. 启动嵌入式服务器
对于 Web 应用,Spring Boot 会启动嵌入式服务器(如 Tomcat、Jetty 或 Undertow),并将应用部署到服务器上。
9. 应用就绪
最后,Spring Boot 应用启动完成,处于就绪状态,开始接受请求。
总结
Spring Boot 的启动过程通过自动配置和约定优于配置的方式,大大简化了 Spring 应用的配置和启动流程,使得开发者能够快速构建和部署应用。如果你需要更详细的某个步骤或相关技术的解释,可以告诉我!
2.说说SpringIOC控制反转流程
3.如何进行依赖注入
4.说说Spring中用到类哪些设计模式
在 Spring 中,使用了多种设计模式,以实现灵活性、可扩展性和可维护性。常见的设计模式包括:
单例模式(Singleton):
- Spring 默认的 Bean 范围是单例的,即每个 Bean 在 Spring 容器中只有一个实例。这种模式确保了全局访问同一个对象。
工厂模式(Factory):
- Spring 使用工厂模式来创建和管理 Bean。
BeanFactory
和ApplicationContext
是工厂类,负责创建和配置 Bean。代理模式(Proxy):
- Spring AOP(面向切面编程)广泛使用代理模式,通过动态代理(JDK 动态代理和 CGLIB)来实现方法拦截和增强功能。
模板方法模式(Template Method):
- 在 Spring JDBC 和 Spring MVC 中使用了模板方法模式,提供一个模板(如
JdbcTemplate
和RestTemplate
),用户只需实现某些步骤的具体细节。观察者模式(Observer):
- Spring 事件机制基于观察者模式,允许应用程序发布和订阅事件。
ApplicationEvent
和ApplicationListener
是相关的类。策略模式(Strategy):
- Spring 通过接口和实现类组合来实现策略模式。例如,使用
HandlerMapping
和HandlerAdapter
来处理不同类型的请求。装饰者模式(Decorator):
- Spring 的
AOP
可以看作是一种装饰者模式,通过增强现有类的功能而不改变其结构。责任链模式(Chain of Responsibility):
- 在 Spring MVC 中,处理请求的多个过滤器和拦截器可以看作是责任链模式。每个拦截器可以选择继续处理或终止请求。
适配器模式(Adapter):
- Spring 的许多组件(如
JdbcTemplate
和DataSource
)使用适配器模式,使得不同的实现可以互操作。通过这些设计模式,Spring 提供了灵活的架构和可扩展的功能,帮助开发者快速构建和维护应用程序。
5.说说Springboot开发中的常见注解以及作用?
在 Spring Boot 开发中,常见的注解及其作用包括:
@SpringBootApplication:该注解是一个组合注解,包含了
@Configuration
、@EnableAutoConfiguration
和@ComponentScan
,用于标记主配置类,启动 Spring Boot 应用。@RestController:结合了
@Controller
和@ResponseBody
,用于创建 RESTful 控制器,处理 HTTP 请求并返回 JSON 数据。@RequestMapping:用于映射 HTTP 请求到相应的处理方法,可以指定请求路径、请求方法等。
@GetMapping、@PostMapping、@PutMapping、@DeleteMapping:这些是
@RequestMapping
的快捷方式,分别用于处理 GET、POST、PUT 和 DELETE 请求。@Autowired:用于自动注入依赖,可以标记在构造器、字段或 setter 方法上。
@Component:标记一个类为 Spring 管理的组件,Spring 会自动检测并注册该类为 Bean。
@Service:用于标记服务层的组件,通常用于业务逻辑处理。
@Repository:用于标记数据访问层的组件,通常用于持久化逻辑。
@Configuration:用于定义 Spring 的配置类,通常包含 Bean 的定义。
@Value:用于注入外部配置(如 application.properties 或 application.yml)中的值。
@Profile:用于指定 Bean 在特定环境下的激活条件,常用于区分开发、测试和生产环境。
@Transactional:用于声明事务,标记在类或方法上,控制事务的边界。
这些注解帮助简化配置和开发,使 Spring Boot 应用更加易于管理和扩展。理解它们的作用和用法,有助于提高开发效率。
6.说说@Resource与@Autowire的区别
@Resource
属性注入优先使用@Resource
默认按照Bean名字从容器中获取
默认的springBean名字时类对应的小驼峰
不同包下有可能存在同名类
解决办法->@Component注解在创建Bean的时候指定名字
@Resource从ioc容器获取时也指定名字
DI:从ioc容器中获取已经创建好的对象给属性(成员变量)赋值
给一个类的属性(成员变量)赋值 有几种方式:四种
1.直接等于号赋值
2.构造器
3.set方法
4.反射
@Autowired 一般使用在构造器赋值和set方法赋值时
所以收SpringDi注入有三种方式
字段(属性)DI ->@Resource
构造器DI -> @Autowired
set方法DI -> @Autowired
@Resource 与 @Autowired使用:
如果一个SpringBean类中值需要注入很少的其他的Bean对象->优先使用@Resource
如果一个SpringBean类中值需要注入很多的其他的Bean对象->优先使用@Autowired
7.使用 springbean时要注意的问题
1.非bean不能调用bean
2.不能形成循环依赖->如何解决
在 Spring Boot 中,循环依赖问题指的是两个或多个 Bean 互相依赖,导致依赖无法被正确注入。这种情况可能导致应用程序在启动时抛出异常。常见的解决循环依赖的方法包括以下几种:
1. 使用
@Lazy
注解可以在其中一个或多个 Bean 的依赖上使用
@Lazy
注解,这样 Spring 容器在第一次需要这个 Bean 时才会创建它,从而打破循环依赖。@Component public class A { private final B b; @Autowired public A(@Lazy B b) { this.b = b; } }
2. 使用
setter
注入如果使用构造器注入导致循环依赖,可以考虑使用
setter
注入。这样,Spring 可以在 Bean 初始化后再注入依赖。@Component public class A { private B b; @Autowired public void setB(B b) { this.b = b; } }
3. 拆分循环依赖
如果可能的话,重新设计你的类结构,避免循环依赖。例如,将某些通用的功能提取到一个独立的 Bean 中,或者考虑是否可以通过事件机制来解耦。
4. 使用
@PostConstruct
或@EventListener
有时候,你可以延迟某些依赖的初始化直到所有 Bean 完全初始化后,这样可以避免循环依赖。例如,你可以在一个 Bean 的
@PostConstruct
方法中手动注入另一个 Bean。@Component public class A { private B b; @Autowired public A() { // No injection in constructor to avoid circular dependency } @Autowired public void setB(B b) { this.b = b; } @PostConstruct public void init() { // Do something after all beans are initialized } }
5. 使用
ObjectFactory
或Provider
接口通过注入
ObjectFactory
或Provider
来延迟获取依赖的实例,从而打破循环依赖。@Component public class A { private final ObjectFactory<B> bFactory; @Autowired public A(ObjectFactory<B> bFactory) { this.bFactory = bFactory; } public void someMethod() { B b = bFactory.getObject(); // Lazily fetch B when needed } }
6. 避免循环依赖的设计
从设计层面上避免循环依赖通常是最理想的解决方案。通过仔细分析你的类之间的依赖关系,重构代码以去除循环依赖。
7. 构造器注入中无法解决的情况
如果使用构造器注入并且无法重构代码,考虑用工厂模式或引入中间层来拆分依赖链。
小结
Spring 默认支持 setter 注入的循环依赖处理,但在使用构造器注入时,如果遇到循环依赖,需要考虑使用延迟加载、重构代码结构或者使用依赖注入的其他高级特性来解决这个问题。最好还是从设计上避免循环依赖,这样可以减少复杂性和潜在的错误。