1.概念:Spring 是一种轻量级开发框架,旨在提高开发人员的开发效率以及系统的可维护性。我们一般说 Spring 框架指的都是 Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发。Spring的两大核心是IOC和AOP。
2.Spring的体系架构(有什么模块)
Spring Core: 基础,可以说 Spring 其他所有的功能都需要依赖于该类库。主要提供 IoC 依赖注入功能。
Spring Aspects : 该模块为与AspectJ的集成提供支持。
Spring AOP :提供了面向切面的编程实现。
Spring JDBC : Java数据库连接。
Spring JMS :Java消息服务。
Spring ORM : 用于支持Hibernate等ORM工具。
Spring Web : 为创建Web应用程序提供支持。
Spring Test : 提供了对 JUnit 和 TestNG 测试的支持。
3.Spring的优点和缺点:
优点:
(1)方便解耦,简化开发。将对象间的依赖关系交给SpringIOC容器管理,降低了程序间的耦合,让程序员更关注应用逻辑。
(2)支持AOP面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能。
(3)支持声明式事务管理,只需要通过配置就可以完成对事务的管理,而无需手动编程。
(4)方便测试,Spring对Junit4支持,可以通过注解方便的测试Spring程序。
(5)像一个粘合剂,可以很好的和各种优秀开源框架整合
缺点
(1)Spring依赖反射,而反射影响性能
(2) 配置繁多,xml文件管理起来困难
1.IOC概念:IOC即(Inversion Of Control) 控制反转,控制就是创建对象的控制权,反转就是反转了资源获取的方向,即将控制权交给外部环境。IOC是一种设计思想,不是一种具体的技术,在其他语言中也有应用,非Spring独有。
IOC的好处:
(1)降低对象间的耦合
(2)资源变得容易管理,比如咱们使用SpringIOC容器的话就很容易实现一个单例。
2.IOC容器:
IoC 容器是 Spring 用来实现 IoC 的载体,IoC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。 在实际项目中一个 Service 类可能有几百甚至上千个类作为它的底层,假如我们需要实例化这个 Service,你可能要每次都要搞清这个 Service 所有底层类的构造函数,这可能会把人逼疯。如果利用 IoC 的话,你只需要配置好,然后在需要的地方引用就行了,这大大增加了项目的可维护性且降低了开发难度。
3.IOC容器在Spring中的实现
(1)前提:Spring中有IOC思想, IOC思想必须基于 IOC容器来完成, 而IOC容器在最底层实质上就是一个对象工厂.
(2)Spring提供了IOC容器的两种实现方式
① BeanFactory:IOC容器的基本实现,是Spring内部的基础设施,是面向Spring本身的,不是提供给开发人员使用的。
② ApplicationContext:BeanFactory的子接口,提供了更多高级特性。面向Spring的使用者,几乎所有场合都使用ApplicationContext而不是底层的BeanFactory。
区别:(1)两者的关系:ApplicationContext是BeanFactoty的子接口,因而提供BeanFactory所有的功能。ApplicationContext以一种更向面向框架的方式工作以及对上下文进行分层和实现继承,ApplicationContext包还提供了以下的功能:
• MessageSource, 提供国际化的消息访问
• 资源访问,如URL和文件
• 事件传播
• 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层
(2)加载bean的时机不同:
ApplicationContex:它在构建容器时,创建对象采用立即加载的策略,也就是说加载完配置文件后,就完成了bean对象的初始化
BeanFactory:它在构建容器时,创建对象采用延迟加载,也就是说当我们第一次要用到这个对象时,才初始化bean。
4.ApplicationContext的三个常用实现类:
(1) ClassPathXmlApplicationContext:它可以加载类路径下的配置文件,要求配置文件必须在类路径下。不在的话,加载不了。(更常用)
(2) FileSystemXmlApplicationContext:它可以加载磁盘任意路径下的配置文件(必须有访问权限)
(3) AnnotationConfigApplicationContext:它是用于读取注解创建容器的
5.依赖注入(DI):
(1)概念:依赖注入是IOC的最常见的实现方式(IOC的另一种表述方式),即组件以一些预先定义好的方式(例如:setter 方法)接受来自于容器的资源注入。相对于IOC而言,这种表述更直接。
(2)注入的数据类型:
基本类型和String
其他bean类型(在配置文件中或者注解配置过的bean)
复杂类型/集合类型
(3)注入的方式:
a.构造器注入:
使用的标签:constructor-arg
标签出现的位置:bean标签的内部
标签中的属性:
type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型
index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值。索引的位置是从0开始
name:用于指定给构造函数中指定名称的参数赋值 常用的
=============以上三个用于指定给构造函数中哪个参数赋值===============================
value:用于提供基本类型和String类型的数据
ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象
优势:
在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功。
弊端:
改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供。
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<constructor-arg name="name" value="泰斯特"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
<!-- 配置一个日期对象 -->
<bean id="now" class="java.util.Date"></bean>
b.set方法注入:
c.通过注解注入
ps:如何注入一个集合?
<!-- 复杂类型的注入/集合类型的注入
用于给List结构集合注入的标签:
list array set
用于个Map结构集合注入的标签:
map props
结构相同,标签可以互换
-->
6.Spring是如何解决循环依赖的?
7.IOC容器的启动流程:
1.bean的三种创建方式:
(1)通过默认的构造函数创建
(2)实例工厂创建
(3)静态工厂创建
<!--创建Bean的三种方式 -->
<!-- 第一种方式:使用默认构造函数创建。
在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时。
采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>
-->
<!-- 第二种方式: 使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器)
<bean id="instanceFactory" class="com.itheima.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>
-->
<!-- 第三种方式:使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象,并存入spring容器)
<bean id="accountService" class="com.itheima.factory.StaticFactory" factory-method="getAccountService"></bean>
-->
2.bean的作用域:
<!-- bean的作用范围调整
bean标签的scope属性:
作用:用于指定bean的作用范围
取值: 常用的就是单例的和多例的
singleton:单例的(默认值)
prototype:多例的
request:作用于web应用的请求范围
session:作用于web应用的会话范围
global-session:作用于集群环境的会话范围(全局会话范围),当不是集群环境时,它就是session
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl" scope="prototype"></bean>
-->
3.bean的生命周期:
(1)创建过程:
①bean实例化以及设置bean的属性
②如果实现了特定的*Aware接口:
如果bean实现了BeanNameAware接口,Spring将bean的ID传递给setBean-Name()方法;
如果bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入;
如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在的应用上下文的引用传入进来;
③若实现了BeanPostProcess接口,调用前置初始化方法postProcessBeforeInitialization()来在bean实例化之后添加一些自定义的处理逻辑
④若实现了InitalizingBean接口,则调用aferPropertiesSet()方法做一些属性被设置之后自定义的事情。
⑤调用bean自身自定义的init-method方法,做一些初始化相关的事情
⑥若实现了BeanPostProcess接口,调用后置初始化方法postProcessAfterInitialization()来在bean实例初始化后的自定义工作
⑦bean初始化完毕
(2)销毁过程:
①若实现了DisableBean接口,则会调用destory()方法
②若bean配置了destory-method方法,则会调用配置的销毁方法
4.Spring 中的单例 bean 的线程安全问题了解吗?
大部分时候我们并没有在系统中使用多线程,所以很少有人会关注这个问题。单例 bean 存在线程问题,主要是因为当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。
常见的有两种解决办法:
在Bean对象中尽量避免定义可变的成员变量(不太现实)。
在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式)。
曾经XML的配置:
1.用于创建对象的
他们的作用就和在XML配置文件中编写一个标签实现的功能是一样的
@Component:
作用:用于把当前类对象存入spring容器中
属性:
value:用于指定bean的id。当我们不写时,它的默认值是当前类名,且首字母改小写。
@Controller:一般用在表现层
@ Service:一般用在业务层
@ Repository:一般用在持久层
以上三个注解他们的作用和属性与Component是一模一样。
他们三个是spring框架为我们提供明确的三层使用的注解,使我们的三层对象更加清晰
2.用于注入数据的
他们的作用就和在xml配置文件中的bean标签中写一个标签的作用是一样的
@Autowired:
作用:自动按照类型注入。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功
如果ioc容器中没有任何bean的类型和要注入的变量类型匹配,则报错。
如果Ioc容器中有多个类型匹配时:
出现位置:
可以是变量上,也可以是方法上
细节:
在使用注解注入时,set方法就不是必须的了。
@Qualifier:
作用:在按照类中注入的基础之上再按照名称注入。它在给类成员注入时不能单独使用。但是在给方法参数注入时可以(稍后我们讲)
属性:
value:用于指定注入bean的id。
@Resource
作用:直接按照bean的id注入。它可以独立使用
属性:
name:用于指定bean的id。
以上三个注入都只能注入其他bean类型的数据,而基本类型和String类型无法使用上述注解实现。
另外,集合类型的注入只能通过XML来实现。
@ Value
作用:用于注入基本类型和String类型的数据
属性:
value:用于指定数据的值。它可以使用spring中SpEL(也就是spring的el表达式)
SpEL的写法:${表达式}
3.用于改变作用范围的
他们的作用就和在bean标签中使用scope属性实现的功能是一样的
@Scope
作用:用于指定bean的作用范围
属性:
value:指定范围的取值。常用取值:singleton prototype
4.和生命周期相关 了解
他们的作用就和在bean标签中使用init-method和destroy-methode的作用是一样的
@PreDestroy
作用:用于指定销毁方法
@PostConstruct
作用:用于指定初始化方法
5.新注解:
@Configuration 作用: 用于指定当前类是一个spring配置类,当创建容器时会从该类上加载注解。获取容器时需要使用AnnotationApplicationContext(有@Configuration注解的类.class)。 属性: value:用于指定配置类的字节码
@ComponentScan 作用: 用于指定spring在初始化容器时要扫描的包。作用和在spring的xml配置文件中的:
@Bean 作用: 该注解只能写在方法上,表明使用此方法创建一个对象,并且放入spring容器。 属性: name:给当前@Bean注解方法创建的对象指定一个名称(即bean的id)。
@PropertySource 作用:
用于加载.properties文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到properties配置文件中,就可以使用此注解指定properties配置文件的位置。 属性: value[]:用于指定properties文件位置。如果是在类路径下,需要写上classpath
@Import 作用: 用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration注解。当然,写上也没问题。 属性: value[]:用于指定其他配置类的字节码。