1、Spring 是什么?特性?有哪些模块?
Spring 是一个轻量级、非入侵式的控制反转 (IoC) 和面向切面 (AOP) 的框架。
1.1 Spring 有哪些特性呢?
- IoC 和 DI 的支持:Spring 的核心就是一个大的工厂容器,可以维护所有对象的创建和依赖关系,Spring 工厂用于生成 Bean,并且管理 Bean 的生命周期,实现高内聚低耦合的设计理念。
- AOP 编程的支持:Spring 提供了面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等切面功能。
- 声明式事务的支持:支持通过配置就来完成对事务的管理,而不需要通过硬编码的方式,以前重复的一些事务提交、回滚的 JDBC 代码,都可以不用自己写了。
- 快捷测试的支持:Spring 对 Junit 提供支持,可以通过注解快捷地测试 Spring 程序。
- 快速集成功能:方便集成各种优秀框架,Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz 等)的直接支持。
- 复杂 API 模板封装:Spring 对 JavaEE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等)都提供了模板化的封装,这些封装 API 的提供使得应用难度大大降低。
1.2 简单说一下什么是AOP 和 IoC?
AOP:面向切面编程,是一种编程范式,它的主要作用是将那些与核心业务逻辑无关,但是对多个对象产生影响的公共行为封装起来,如日志记录、性能统计、事务等。
IoC:控制反转,是一种设计思想,它的主要作用是将对象的创建和对象之间的调用过程交给 Spring 容器来管理。
2、Spring 有哪些模块呢?
Spring 框架是分模块存在,除了最核心的 Spring Core Container 是必要模块之外,其他模块都是可选,大约有 20 多个模块。最主要的七大模块:
- Spring Core:Spring 核心,它是框架最基础的部分,提供 IoC 和依赖注入 DI 特性。
- Spring Context:Spring 上下文容器,它是 BeanFactory 功能加强的一个子接口。
- Spring Web:它提供 Web 应用开发的支持。
- Spring MVC:它针对 Web 应用中 MVC 思想的实现。
- Spring DAO:提供对 JDBC 抽象层,简化了 JDBC 编码,同时,编码更具有健壮性。
- Spring ORM:它支持用于流行的 ORM 框架的整合,比如:Spring + Hibernate、Spring + iBatis、Spring + JDO 的整合等。
- Spring AOP:即面向切面编程,它提供了与 AOP 兼容的编程实现。
3、Spring 有哪些常用注解呢?
Spring 提供了大量注解简化 Java 应用的开发和配置,主要用于 Web 开发、往容器注入 Bean、AOP、事务控制等。
3.1 Web 开发方面有哪些注解呢?
- @Controller:用于标注控制层组件。
- @RestController:是 @Controller 和 @ResponseBody 的结合体,返回 JSON 数据时使用。
- @RequestMapping:用于映射请求 URL 到具体的方法上,还可以细分为:
@PostMapping:只能用于处理 POST 请求
@DeleteMapping:只能用于处理 DELETE 请求
@PutMapping:只能用于处理 PUT 请求
@GetMapping:只能用于处理 GET 请求 - @ResponseBody:直接将返回的数据放入 HTTP 响应正文中,一般用于返回 JSON 数据。
- @RequestBody:表示一个方法参数应该绑定到 Web 请求体。
- @PathVariable:用于接收路径参数,比如 @RequestMapping(“/hello/{name}”),name 就是路径参数。
- @RequestParam:用于接收请求参数。比如 @RequestParam(name = “key”) String key,key 就是请求参数。
3.2 容器类注解有哪些呢?
- @Component:标识一个类为 Spring 组件,使其能够被 Spring 容器自动扫描和管理。
- @Controller:标识一个控制器组件(控制层)。
- @Service:标识一个业务逻辑组件(服务层)。
- @Repository:标识一个数据访问组件(持久层)。
- @Autowired:按类型自动注入依赖。
- @Resource:按名称自动注入依赖。
- @Configuration:用于定义配置类,可替换 XML 配置文件。
- @Value:用于将 Spring Boot 中 application.properties 配置的属性值赋值给变量。
3.3 AOP 方面有哪些注解呢?
@Aspect 用于声明一个切面,可以配合其他注解一起使用,比如:
@After:在方法执行之后执行。
@Before:在方法执行之前执行。
@Around:方法前后均执行。
@PointCut:定义切点,指定需要拦截的方法。
3.4 事务注解有哪些?
主要就是 @Transactional,用于声明一个方法需要事务支持。
4、Spring 中应用了哪些设计模式呢?
- 工厂模式:BeanFactory 和 ApplicationContext,实现 Bean 的创建和管理。
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MyBean myBean = context.getBean(MyBean.class);
- 单例模式:这样可以保证 Bean 的唯一性,减少系统开销。
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MyService myService1 = context.getBean(MyService.class);
MyService myService2 = context.getBean(MyService.class);
// This will print "true" because both references point to the same instance
System.out.println(myService1 == myService2);
- 代理模式:来实现 AOP 横切关注点(如事务管理、日志记录、权限控制等)
@Transactional
public void myTransactionalMethod() {
// 方法实现
}
4.1 Spring如何实现单例模式?
Spring 通过 IOC 容器实现单例模式,具体步骤是:单例 Bean 在容器初始化时创建并使用 DefaultSingletonBeanRegistry 提供的 singletonObjects 进行缓存。在请求 Bean 时,Spring 会先从缓存中获取。
// 单例缓存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
public Object getSingleton(String beanName) {
return this.singletonObjects.get(beanName);
}
protected void addSingleton(String beanName, Object singletonObject) {
this.singletonObjects.put(beanName, singletonObject);
}
5、Spring 容器、Web 容器之间的区别?
Spring 容器是 Spring 框架的核心部分,负责管理应用程序中的对象生命周期和依赖注入。
Web 容器(也称 Servlet 容器),是用于运行 Java Web 应用程序的服务器环境,支持 Servlet、JSP 等 Web 组件。常见的 Web 容器包括 Apache Tomcat、Jetty等。
Spring MVC 是 Spring 框架的一部分,专门用于处理 Web 请求,基于 MVC(Model-View-Controller)设计模式。
6、说一说什么是 IoC、DI?
所谓的 IoC,就是由容器来控制对象的生命周期和对象之间的关系。控制对象生命周期的不再是引用它的对象,而是容器,这就叫控制反转(Inversion of Control)。于是,对于某个对象来说,以前是它控制它依赖的对象,现在是所有对象都被 Spring 控制。IOC 是一种思想,DI 是实现 IOC 的具体方式,比如说利用注入机制(如构造器注入、Setter 注入)将依赖传递给目标对象。
6.1 为什么要使用 IoC 呢?
在平时的 Java 开发中,如果我们要实现某一个功能,可能至少需要两个以上的对象来协助完成,在没有 Spring 之前,每个对象在需要它的合作对象时,需要自己 new 一个,比如说 A 要使用 B,A 就对 B 产生了依赖,也就是 A 和 B 之间存在了一种耦合关系。有了 Spring 之后,就不一样了,创建 B 的工作交给了 Spring 来完成,Spring 创建好了 B 对象后就放到容器中,A 告诉 Spring 我需要 B,Spring 就从容器中取出 B 交给 A 来使用。这就是 IoC 的好处,它降低了对象之间的耦合度,使得程序更加灵活,更加易于维护。
7、说说 BeanFactory 和 ApplicantContext?
BeanFactory 位于整个 Spring IoC 容器的顶端,ApplicationContext 算是 BeanFactory 的子接口。最主要的方法就是 getBean(),这个方法负责从容器中返回特定名称或者类型的 Bean 实例。ApplicationContext 继承了 HierachicalBeanFactory 和 ListableBeanFactory 接口,是 BeanFactory 的自动挡版本,是 Spring 应用的默认方式。
8、你知道 Spring 容器启动阶段会干什么吗?
Spring 的 IoC 容器工作的过程可以划分为两个阶段:容器启动阶段和 Bean 实例化阶段。其中容器启动阶段主要做的工作是加载和解析配置文件,保存到对应的 Bean 定义中。
8.1 说说 Spring 的 Bean 实例化方式
- 构造方法的方式:在类上使用 @Component(或@Service、@Repository 等特定于场景的注解)标注类,然后通过构造方法注入依赖。
@Component
public class ExampleBean {
private DependencyBean dependency;
@Autowired
public ExampleBean(DependencyBean dependency) {
this.dependency = dependency;
}
}
- 静态工厂的方式:在这种方式中,Bean 是由一个静态方法创建的,而不是直接通过构造方法。
public class ClientService {
private static ClientService clientService = new ClientService();
private ClientService() {}
public static ClientService createInstance() {
return clientService;
}
}
- 实例工厂方法的方式:与静态工厂方法相比,实例工厂方法依赖于某个类的实例来创建 Bean。这通常用在需要通过工厂对象的非静态方法来创建 Bean 的场景。
public class ServiceLocator {
public ClientService createClientServiceInstance() {
return new ClientService();
}
}
- FactoryBean 接口的方式:FactoryBean 是一个特殊的 Bean 类型,可以在 Spring 容器中返回其他对象的实例。通过实现 FactoryBean 接口,可以自定义实例化逻辑,这对于构建复杂的初始化逻辑非常有用。
public class ToolFactoryBean implements FactoryBean<Tool> {
private int factoryId;
private int toolId;
@Override
public Tool getObject() throws Exception {
return new Tool(toolId);
}
@Override
public Class<?> getObjectType() {
return Tool.class;
}
@Override
public boolean isSingleton() {
return true;
}
// setter and getter methods for factoryId and toolId
}
9、你是怎么理解 Bean 的?
Bean 是指由 Spring 容器管理的对象,它的生命周期由容器控制,包括创建、初始化、使用和销毁。通过三种方式声明:注解方式、XML 配置、Java 配置。
- 使用 @Component、@Service、@Repository、@Controller 等注解定义,主流。
- 基于 XML 配置,Spring Boot 项目已经不怎么用了。
- 使用 Java 配置类创建 Bean:
@Configuration
public class AppConfig {
@Bean
public UserService userService() {
return new UserService();
}
}
9.1 @Component 和 @Bean 的区别
@Component 是 Spring 提供的一个类级别注解,由 Spring 自动扫描并注册到 Spring 容器中。@Bean 是一个方法级别的注解,用于显式地声明一个 Bean,当我们需要第三方库或者无法使用 @Component 注解类时,可以使用 @Bean 来将其实例注册到容器中。
10、能说一下 Bean 的生命周期吗?
Bean 的生命周期大致分为五个阶段:
- 实例化:Spring 容器根据 Bean 的定义创建 Bean 的实例,相当于执行构造方法,也就是 new 一个对象。
- 属性赋值:相当于执行 setter 方法为字段赋值。
- 初始化:初始化阶段允许执行自定义的逻辑,比如设置某些必要的属性值、开启资源、执行预加载操作等,以确保 Bean 在使用之前是完全配置好的。
- 销毁:相当于执行 = null,释放资源。
11、为什么 IDEA 不推荐使用 @Autowired 注解注入 Bean?
这是因为字段注入的方式不能像构造方法那样使用 final 注入不可变对象。
11.1 @Autowired 和 @Resource 注解的区别?
@Autowired 是 Spring 提供的注解,按类型(byType)注入。
@Resource 是 Java EE 提供的注解,按名称(byName)注入。