Spring 基础知识

2022-02-10  本文已影响0人  小郭子

来源:公众号 作者:Java知音
链接:https://mp.weixin.qq.com/s/45yy2qNIAI7ltrOPvCsNSw

Sping原理

Spring是一个轻量级Java开发框架,最早有Rod Johnson创建,目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题。它是一个分层的JavaSE/JavaEE full-stack(一站式)轻量级开源框架,为开发Java应用程序提供全面的基础架构支持。Spring负责基础架构,因此Java开发者可以专注于应用程序的开发。

Spring是一个全面的、企业应用开发一站式的解决方案,贯穿表现层、业务层、持久层。但是它仍然可以和其他的框架无缝整合。

Spring 特点

轻量级: 组件大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1M多的JAR文件中发布,并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式,典型案例,Spring应用中的对象不依赖于Spring特定的类
控制反转: Spring通过控制反转(IOC)技术实现解耦。一个对象依赖的其他对象会通过被动的方式传递进来,而不需要对象自己创建或者查找依赖。
面向切面: 支持切面(AOP)编程,并且把应用业务逻辑和系统服务区分开。
容器: Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器。可以配置每个bean如何被创建、销毁,bean的作用范围是单例还是每次都生成一个新的实例,以及他们是如何相互关联。
框架集合: 将简单的组件配置,组合成为复杂的框架;应用对象被申明式组合;提供许多基础功能(事务管理、持久化框架继承),提供应用逻辑开发接口

Spring 框架优缺点

优点

缺点

Spring 框架中都用到了哪些设计模式

Spring 框架中使用到了大量的设计模式,下面列举了比较有代表性的:

Spring核心组件

Spring 总共大约有 20 个模块, 由 1300 多个不同的文件构成。而这些组件被分别整合在核心容器(Core Container) 、 AOP(Aspect Oriented Programming)和设备支持(Instrmentation) 、数据访问与集成(Data Access/Integeration) 、 Web、 消息(Messaging) 、 Test等 6 个模块中。以下是 Spring 5 的模块结构图:


spring 核心组件

Spring 控制反转(IOC)

控制反转(IOC)概念
控制反转即IOC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。

Spring 通过一个配置文件描述 Bean 及 Bean 之间的依赖关系,利用 Java 语言的反射功能(依赖注入DI)实例化 Bean 并建立 Bean 之间的依赖关系。Spring 的 IoC 容器在完成这些底层工作的基础上,还提供 了 Bean 实例缓存、生命周期管理、 Bean 实例代理、事件发布、资源装载等高级服务。

Spring 容器高层视图
Spring 启动时读取应用程序提供的 Bean 配置信息,并在 Spring 容器中生成一份相应的 Bean 配

置注册表,然后根据这张注册表实例化 Bean,装配好 Bean 之间的依赖关系,为上层应用提供准

备就绪的运行环境。其中 Bean 缓存池为 HashMap 实现

IOC 容器实现

BeanFactory-框架基础设施
BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;

ApplicationContext 面向使用Spring 框架的开发者,几乎所有的应用场合我们都直接使用 ApplicationContext 而非底层的 BeanFactory。

ApplicationContext 面向开发应用

ApplicationContext 由 BeanFactory 派生而来,提供了更多面向实际应用的功能。
ApplicationContext 继承了 HierarchicalBeanFactory 和 ListableBeanFactory 接口,在此基础上,还通过多个其他的接口扩展了 BeanFactory 的功能:


ApplicationContext类继承体系

BeanFactory 和 ApplicationContext有什么区别?

BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。

依赖关系

BeanFactory:是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。

ApplicationContext:接口作为BeanFactory的派生,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能:

加载方式

BeanFactroy:采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调getBean()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。

ApplicationContext:它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。ApplicationContext启动后预载入所有的单实例Bean,通过预载入单实例bean ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。

相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。

创建方式

BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader。

注册方式

BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。

ApplicationContext通常的实现

Spring的依赖注入

其主要实现方式有两种:依赖注入和依赖查找。

依赖注入: 相对于IoC而言,依赖注入(DI)更加准确地描述了IoC的设计理念。所谓依赖注入(Dependency Injection),即组件之间的依赖关系由容器在应用系统运行期来决定,也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。

依赖注入的基本原则
应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由IoC容器负责,“查找资源”的逻辑应该从应用组件的代码中抽取出来,交给IoC容器负责。容器全权负责组件的装配,它会把符合依赖关系的对象通过属性(JavaBean中的setter)或者是构造器传递给需要的对象。

依赖注入优势
依赖注入之所以更流行是因为它是一种更可取的方式:让容器全权负责依赖查询,受管组件只需要暴露JavaBean的setter方法或者带参数的构造器或者接口,使容器可以在初始化时组装对象的依赖关系。其与依赖查找方式相比,主要优势为:

依赖注入实现方式
依赖注入是时下最流行的IoC实现方式,依赖注入分为接口注入(Interface Injection),Setter方法注入(Setter Injection)和构造器注入(Constructor Injection)三种方式。其中接口注入由于在灵活性和易用性比较差,现在从Spring4开始已被废弃。

构造器依赖注入和 Setter方法注入的区别

注入方式比较

两种依赖方式都可以使用,构造器注入和Setter方法注入。最好的解决方案是用构造器参数实现强制依赖,setter方法实现可选依赖。

WebApplication 体系架构

WebApplicationContext 是专门为 Web 应用准备的,它允许从相对于 Web 根目录的路径中装载配置文件完成初始化工作。从 WebApplicationContext 中可以获得ServletContext 的引用,整个 Web 应用上下文对象将作为属性放置到 ServletContext 中,以便 Web 应用环境可以访问 Spring 应用上下文。


WebApplication 体系架构

Spring Bean 定义

一个Spring Bean 的定义包含容器必知的所有配置元数据,包括如何创建一个bean,它的生命周期详情及它的依赖。

Spring Bean 作用域

Spring 3 中为 Bean 定义了 5 中作用域,分别为 singleton(单例)、prototype(原型)、request、session 和 global session,5 种作用域说明如下:

Spring处理线程并发问题

在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域,因为Spring对一些Bean中非线程安全状态采用ThreadLocal进行处理,解决线程安全问题。

ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。而ThreadLocal采用了“空间换时间”的方式。

ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。

Spring Bean 生命周期

Spring Bean 生命周期

实例化

  1. 实例化一个 Bean,也就是我们常说的 new。

IOC 依赖注入

  1. 按照 Spring 上下文对实例化的 Bean 进行配置,也就是 IOC 注入。

setBeanName 实现

  1. 如果这个 Bean 已经实现了 BeanNameAware 接口,会调用它实现的 setBeanName(String)方法,此处传递的就是 Spring 配置文件中 Bean 的 id 值

BeanFactoryAware 实现

  1. 如果这个 Bean 已经实现了 BeanFactoryAware 接口,会调用它实现的 setBeanFactory,setBeanFactory(BeanFactory)传递的是 Spring 工厂自身(可以用这个方式来获取其它 Bean,只需在 Spring 配置文件中配置一个普通的 Bean 就可以)。

ApplicationContextAware 实现

  1. 如果这个 Bean 已经实现了 ApplicationContextAware 接口,会调用setApplicationContext(ApplicationContext)方法,传入 Spring 上下文(同样这个方式也可以实现步骤 4 的内容,但比 4 更好,因为 ApplicationContext 是 BeanFactory 的子接口,有更多的实现方法)

postProcessBeforeInitialization 接口实现-初始化预处理

  1. 如果这个 Bean 关联了 BeanPostProcessor 接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor 经常被用作是 Bean 内容的更改,并且由于这个是在 Bean 初始化结束时调用那个的方法,也可以被应用于内存或缓存技术。

init-method

  1. 如果 Bean 在 Spring 配置文件中配置了 init-method 属性会自动调用其配置的初始化方法。

postProcessAfterInitialization

  1. 如果这个 Bean 关联了 BeanPostProcessor 接口,将会调用postProcessAfterInitialization(Object obj, String s)方法。

注:以上工作完成以后就可以应用这个 Bean 了,那这个 Bean 是一个 Singleton 的,所以一般情况下我们调用同一个 id 的 Bean 会是在内容地址相同的实例,当然在 Spring 配置文件中也可以配置非 Singleton。

Destroy 过期自动清理阶段

  1. 当 Bean 不再需要时,会经过清理阶段,如果 Bean 实现了 DisposableBean 这个接口,会调用那个其实现的 destroy()方法;

destroy-method 自配置清理

  1. 最后,如果这个 Bean 的 Spring 配置中配置了 destroy-method 属性,会自动调用其配置的销毁方法。

bean生命周期方法

bean 标签有两个重要的属性(init-methoddestroy-method)。用它们你可以自己定制初始化和注销方法。它们也有相应的注解(@PostConstruct@PreDestroy)。

<bean id="" class="" init-method="初始化方法" destroy-method="销毁方法">

什么是Spring的内部bean?什么是Spring inner beans?

在Spring框架中,当一个bean仅被用作另一个bean的属性时,它能被声明为一个内部bean。
内部bean可以用setter注入“属性”和构造方法注入“构造参数”的方式来实现,内部bean通常是匿名的,它们的Scope一般是prototype。
Spring 依赖注入四种方式构:
造器注入

/*带参数,方便利用构造器进行注入*/ 
 public CatDaoImpl(String message){
     this. message = message; 
 }
<bean id="CatDaoImpl" class="com.CatDaoImpl"> <constructor-arg value=" message "></constructor-arg> </bean>

setter 方法注入

  public class Id {
 private int id;
 public int getId() { return id; }
 public void setId(int id) { this.id = id; }
}
<bean id="id" class="com.id "> <property name="id" value="123"></property> </bean>

静态工厂注入
静态工厂顾名思义,就是通过调用静态工厂的方法来获取自己需要的对象,为了让 spring 管理所有对象,我们不能直接通过"工程类.静态方法()"来获取对象,而是依然通过 spring 注入的形式获取:

public class DaoFactory { //静态工厂
 
 public static final FactoryDao getStaticFactoryDaoImpl(){
 return new StaticFacotryDaoImpl();
 }
}
 
public class SpringAction {
 private FactoryDao staticFactoryDao; //注入对象
 //注入对象的 set 方法
 public void setStaticFactoryDao(FactoryDao staticFactoryDao) {
 this.staticFactoryDao = staticFactoryDao;
 }
}
<!--factory-method="getStaticFactoryDaoImpl"指定调用哪个工厂方法-->
 <bean name="springAction" class=" SpringAction" >
 <!--使用静态工厂的方法注入对象,对应下面的配置文件-->
 <property name="staticFactoryDao" ref="staticFactoryDao"></property>
 </bean>
 
 <!--此处获取对象的方式是从工厂类中获取静态方法-->
<bean name="staticFactoryDao" class="DaoFactory"
      factory-method="getStaticFactoryDaoImpl"></bean>

实例工厂
实例工厂的意思是获取对象实例的方法不是静态的,所以你需要首先 new 工厂类,再调用普通的实例方法:

  public class DaoFactory { //实例工厂
 
 public FactoryDao getFactoryDaoImpl(){
 return new FactoryDaoImpl();
 }
}
 
public class SpringAction {
 private FactoryDao factoryDao; //注入对象
 public void setFactoryDao(FactoryDao factoryDao) {
 this.factoryDao = factoryDao;
 }
}
<bean name="springAction" class="SpringAction">
 <!--使用实例工厂的方法注入对象,对应下面的配置文件-->
 <property name="factoryDao" ref="factoryDao"></property>
 </bean>
 
 <!--此处获取对象的方式是从工厂类中获取实例方法-->
<bean name="daoFactory" class="com.DaoFactory"></bean>
<bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean>

5 种不同方式的自动装配

Spring 装配包括手动装配和自动装配,手动装配是有基于 xml 装配、构造方法、setter 方法等自动装配有五种自动装配的方式,可以用来指导 Spring 容器用自动装配方式来进行依赖注入。

Spring 中注入一个 Java Collection

Spring 提供了以下四种集合类的配置元素:

<beans> 
 <!-- Definition for javaCollection --> 
 <bean id="javaCollection" class="com.howtodoinjava.JavaCollection"> 
 <!-- java.util.List --> 
 <property name="customList"> 
 <list> 
 <value>INDIA</value> 
 <value>Pakistan</value> 
 <value>USA</value> 
 <value>UK</value> 
 </list> 
 </property> 
 
 <!-- java.util.Set --> 
 <property name="customSet"> 
 <set> 
 <value>INDIA</value> 
 <value>Pakistan</value> 
 <value>USA</value> 
 <value>UK</value> 
 </set> 
 </property> 
 
 <!-- java.util.Map --> 
 <property name="customMap"> 
 <map> 
 <entry key="1" value="INDIA"/> 
 <entry key="2" value="Pakistan"/> 
 <entry key="3" value="USA"/> 
 <entry key="4" value="UK"/> 
 </map> 
 </property> 
 
 <!-- java.util.Properties --> 
 <property name="customProperies"> 
 <props> 
 <prop key="admin">admin@nospam.com</prop> 
 <prop key="support">support@nospam.com</prop> 
 </props> 
 </property> 
 
 </bean> 
</beans>

使用@Autowired注解自动装配的过程

在使用@Autowired注解之前需要在Spring配置文件进行配置,<context:annotation-config />
在启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied@Resource@Inject时,就会在IoC容器自动查找需要的bean,并装配给该对象的属性。在使用@Autowired时,首先在容器中查询对应类型的bean:

Spring AOP

AOP原理

OOP(Object-Oriented Programming)面向对象编程,允许开发者定义纵向的关系,但并适用于定义横向的关系,导致了大量代码的重复,而不利于各个模块的重用。

AOP(Aspect-Oriented Programming),一般称为面向切面编程,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。

AOP 主要应用场景有

AOP 核心概念

Spring 中的代理

将 Advice 应用于目标对象后创建的对象称为代理。在客户端对象的情况下,目标对象和代理对象是相同的。

Advice + Target Object = Proxy

AOP 实现方式

AOP实现的关键在于代理模式,AOP代理主要分为静态代理和动态代理。

AOP 两种代理方式

Spring 提供了两种方式来生成代理对象: JDK Proxy 和 Cglib,具体使用哪种方式生成由AopProxyFactory 根据 AdvisedSupport 对象的配置来决定。默认的策略是如果目标类是接口,则使用 JDK 动态代理技术,否则使用 Cglib 来生成代理。

JDK 动态接口代理

JDK 动态代理主要涉及到 java.lang.reflect 包中的两个类:Proxy 和 InvocationHandler。
InvocationHandler是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编制在一起。
Proxy 利用 InvocationHandler 动态创建一个符合某一接口的实例,生成目标类的代理对象。

CGLib 动态代理

CGLib 全称为 Code Generation Library,是一个强大的高性能,高质量的代码生成类库,可以在运行期扩展 Java 类与实现 Java 接口,CGLib 封装了 asm,可以再运行期动态生成新的 class。和 JDK 动态代理相比较:JDK 创建代理有一个限制,就是只能为接口创建代理实例,而对于没有通过接口定义业务方法的类,则可以通过 CGLib 创建动态代理。

实现原理

@Aspect

 @Pointcut(value="execution(* com.yangxin.core.service.*.*.*(..))")
 public void point(){
 }
 
 @Before(value="point()")
 public void before(){
 System.out.println("transaction begin");
 }
 
 @AfterReturning(value = "point()")
 public void after(){
 System.out.println("transaction commit");
 }
 
 @Around("point()")
 public void around(ProceedingJoinPoint joinPoint) throws Throwable{
 System.out.println("transaction begin");
 joinPoint.proceed();
 System.out.println("transaction commit");
 
 } 
}

Spring在运行时通知对象

通过在代理类中包裹切面,Spring在运行期把切面织入到Spring管理的bean中。代理封装了目标类,并拦截被通知方法的调用,再把调用转发给真正的目标bean。当代理拦截到方法调用时,在调用目标bean方法之前,会执行切面逻辑。
直到应用需要被代理的bean时,Spring才创建代理对象。如果使用的是ApplicationContext的话,在ApplicationContext从BeanFactory中加载所有bean的时候,Spring才会创建被代理的对象。因为Spring运行时才创建代理对象,所以我们不需要特殊的编译器来织入SpringAOP的切面。

Spring只支持方法级别的连接点

因为Spring基于动态代理,所以Spring只支持方法连接点。Spring缺少对字段连接点的支持,而且它不支持构造器连接点。方法之外的连接点拦截功能,我们可以利用Aspect来补充。
在Spring AOP 中,关注点和横切关注的区别是什么?在 spring aop 中 concern 和 cross-cutting concern 的不同之处
关注点(concern)是应用中一个模块的行为,一个关注点可能会被定义成一个我们想实现的一个功能。
横切关注点(cross-cutting concern)是一个关注点,此关注点是整个应用都会使用的功能,并影响整个应用,比如日志,安全和数据传输,几乎应用的每个模块都需要的功能。因此这些都属于横切关注点。

Spring通知类型

在AOP术语中,切面的工作被称为通知,实际上是程序执行时要通过SpringAOP框架触发的代码段。Spring切面可以应用5种类型的通知:

同一个aspect,不同advice的执行顺序:

没有异常情况下的执行顺序:

有异常情况下的执行顺序:

Spring MVC

Spring MVC 原理

Spring 的模型-视图-控制器(MVC)框架是围绕一个 DispatcherServlet 来设计的,这个 Servlet会把请求分发给各个处理器,并支持可配置的处理器映射、视图渲染、本地化、时区与主题渲染等,甚至还能支持文件上传。

Spring MVC原理

Http 请求到 DispatcherServlet
(1) 客户端请求提交到 DispatcherServlet。

HandlerMapping 寻找处理器
(2) 由 DispatcherServlet 控制器查询一个或多个 HandlerMapping,找到处理请求的Controller。

调用处理器 Controller
(3) DispatcherServlet 将请求提交到 Controller。

Controller 调用业务逻辑处理后,返回 ModelAndView
(4)(5)调用业务处理和返回结果:Controller 调用业务逻辑处理后,返回 ModelAndView。

DispatcherServlet 查询 ModelAndView
(6)(7)处理视图映射并返回模型:DispatcherServlet 查询一个或多个 ViewResoler 视图解析器,找到 ModelAndView 指定的视图。

ModelAndView 反馈浏览器 HTTP
(8) Http 响应:视图负责将结果显示到客户端。

Spring DATA

Spring ORM理解

Spring 通过提供ORM模块,支持我们在直接JDBC之上使用一个对象/关系映射映射(ORM)工具,Spring 支持集成主流的ORM框架,如Hiberate,JDO和 iBATIS,JPA,TopLink,JDO,OJB 。Spring的事务管理同样支持以上所有ORM框架及JDBC。

解释JDBC抽象和DAO模块
通过使用JDBC抽象和DAO模块,保证数据库代码的简洁,并能避免数据库资源错误关闭导致的问题,它在各种不同的数据库的错误信息之上,提供了一个统一的异常访问层。它还利用Spring的AOP 模块给Spring应用中的对象提供事务管理服务。

Spring DAO 的支持

Spring DAO(数据访问对象) 使得 JDBC,Hibernate 或 JDO 这样的数据访问技术更容易以一种统一的方式工作。这使得用户容易在持久性技术之间切换。它还允许您在编写代码时,无需考虑捕获每种技术不同的异常。

Spring JDBC API

JdbcTemplate是什么

JdbcTemplate 类提供了很多便利的方法解决诸如把数据库数据转变成基本数据类型或对象,执行写好的或可调用的数据库操作语句,提供自定义的数据错误处理。

使用Spring通过什么方式访问Hibernate?

有两种方式访问Hibernate:

Spring 支持的 ORM

Spring 支持以下 ORM:

如何通过 HibernateDaoSupport 将 Spring 和 Hibernate 结合起来?

用 Spring 的 SessionFactory 调用 LocalSessionFactory。集成过程分三步:

Spring 支持的事务管理类型

Spring 支持两种类型的事务管理:

Spring 框架的事务管理有哪些优点?

它为不同的事务 API 如 JTA,JDBC,Hibernate,JPA 和 JDO,提供一个不变 的编程模式。
它为编程式事务管理提供了一套简单的 API 而不是一些复杂的事务 API 如 它支持声明式事务管理。它和 Spring 各种数据访问抽象层很好得集成。

你更倾向用那种事务管理类型?

大多数 Spring 框架的用户选择声明式事务管理,因为它对应用代码的影响最小,因 此更符合一个无侵入的轻量级容器的思想。声明式事务管理要优于编程式事务管理, 虽然比编程式事务管理(这种方式允许你通过代码控制事务)少了一点灵活性。

Spring常用注解

声明bean的注解

注入bean的注解

指定名称后,如果Spring IOC容器中没有对应的组件bean抛出NoSuchBeanDefinitionException。也可以将@Autowired中required配置为false,如果配置为false之后,当没有找到相应bean的时候,系统不会抛异常

根据类型进行自动装配的,如果需要按名称进行装配,则需要配合@Named

默认根据属性名称进行自动装配的,如果有多个类型一样的Bean候选者,则可以通过name进行指定进行注入

java配置类相关注解

切面(AOP)相关注解

Spring支持AspectJ的注解式切面编程

@Bean的属性支持

@Scope 设置Spring容器如何新建Bean实例(方法上,得有@Bean),其设置类型包括:

@Value注解

为属性注入值,支持如下方式的注入:

注入普通字符


普通字符

注入操作系统属性


操作系统属性

注入表达式结果


表达式结果

注入其它bean属性


其它bean属性

注入文件资源


文件资源

注入网站资源


网站资源

注入配置文件


配置文件

@PropertySource 加载配置文件(类上),还需配置一个PropertySourcesPlaceholderConfigurer的bean。

环境切换

异步相关

定时任务相关

@Enable 注解说明

这些注解主要用来开启对xxx的支持。

测试相关注解

SpringMVC部分

上一篇 下一篇

猜你喜欢

热点阅读