Spring是一个开源框架,Spring为简化企业级应用开发而生。 使用Spring可以使简单的 JavaBean实现以前只有EJB才能实现的功能。 Spring是一个IOC(DlI)和 AOP容器框架;
特点:



<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.3.18version>
dependency>


在resource下配置一个spring-1.xml配置文件,之后通过该配置文件创建我们需要的容器

package edu.etime.springdemo.demo1;
public class Test {
public static void main( String[] args) {
/*一般方法使用HeLLoSpring对象
1、new创建对象实例
2、调用get , set方法获取值或者赋值*/
HelloSpring helloSpring = new HelloSpring();
helloSpring.setName("张三");
helloSpring.setAddr("温江");
system.out.println(helloSpring.getName());
System.out.print1n(helloSpring.getAddr());
}
/*
使用spring容器:
1、创建spring容器
2、从容器中获取指定的bean
*/
//创建容器
ApplicationContext ctx = new ClassPathXm1ApplicationContext("spring-1.xm1");
//从容器中获取bean
HelloSpring hs = (HelloSpring) ctx.getBean("hellospring");
system.out.println(hs.getName()+"\t"+hs.getAddr());
}
IOC(Inversion of Control):其思想是 反转资源获取的方向 .传统的资源查找方式要求组件向容器发起请求查找资源. 作为回应,容器适时的返回资源.而应用了IOC之后,则是 容器主动地将资源推送给它所管理的组件,组件所要做的仅是选择一种合适的方式来接受资源. 这种行为也被称为查找的被动形式
DI(Dependency Injection)—IOC的另一种表述方式:即组件以一些预先定义好的方式(例如: setter方法)接受来自如容器的资源注入.相对于IOC而言,这种表述更直接
IOC 与 DI 两者区别
IOC控制反转
DI依赖注入
<bean id="hellospring" class="edu.etime.spring.HelloSpringTest">
<property name="name" value="Spring配置名"/>
<property name="addr" value="四川成都!"/>
bean>
id 属性 :bean 的名称 ,在IOC容器中,bena的名称是唯一的.hellospring
如果没有指定id属性,那么将会用class属性作为bean的名称edu.etime.spring.HelloSpringTest
Class属性,类的全名称(包名 + 类名)edu.etime.spring.HelloSpringTest
在Spring lOC容器读取 Bean配置创建Bean实例之前,必须对它进行实例化.只有在容器实例化后,才可以从lOC 容器里获取 Bean实例并使用.( 要获取 bean就必须要先实例化IOC容器,然后从容器中获取bean ) .
Spring 提供两种类型的IOC容器实现:
BeanFactory:IOC容器的基本实现;
ApplicationContext: 提供了更多的高级特性,是BeanFactory的子接口; (主要使用的实现容器方式)
ApplicationContext提供的实现类:
ClassPathXmlApplicationContext: 从类路径下加载配置文件。FileSystemXmIApplicationContext: 从文件系统中加载配置文件。
ConfigurableApplicationContext扩展于ApplicationContext,新增加两个主要方法: refresh() 和 close(), 让 ApplicationContext具有启动、刷新和关闭上下文的能力.
ApplicationContext在初始化上下文时就实例化所有单例的 Bean。(默认spirng._容器中的bean都是单例对象)。
WebApplicationContext是专门为wEB应用而准备的,它允许从相对于wEB根目录的路径中完成初始化工作.
ApplicationContext 与 ConfigurableApplicationContext的区别:
ConfigurableApplicationContext是ApplicationContext的子接口,增加了刷新和关闭方法,让IOC容器具备刷新和关闭功能.
两种方式获取Bean
//根据bean的id获取bean
HelloSpring hs = (HelloSpring) ctx.getBean("edu.etime.springdemo.demo1.HelloSpring")
//根据类型获取bean
//注意:相同类型的bean在IOC容器中不能存在多个
Hellospring hs1 = ctx.getBean(HelloSpring.class);
三种注入方式:
通过属性注入(通过setter方法注入)

通过构造方法注入

顺序不同的情况:
①通过index指定

②通过类型

③通过参数名字

如果我们的值带有特殊字符:

那我们可以使用]]>这样的方式注入
组成应用程序的bean经常需要相互写作以完成应用程序的功能.要使bean能够相互访问,就必须在bean配置文件中指定对bean的引用.
<l -- 引用其他的bean -->
<bean id="p1" class="edu.etime.springdemo.beans.Person">
<property name="name " value="张三">property><! --通过属性来引用其他bean -->
<property name="car" ref="car4">property>
bean>
<bean id="p2" class="edu.etime.springdemo.beans.Person">
<property name="name" value="张三">property>
<! --通过属性来应用其他bean -->
<property name="car">
<ref bean="car3" />property>
bean>


<! --内部bean -->
<bean id="p3" class="edu.etime.springdemo. beans.Person">
<property name="name" value="张三" >property>
<! --通过属性来应用其他bean -->
<property name="car">
<bean class="edu.etime. springdemo.beans.car">
<constructor-arg value=”大中国”
index="1 "> constructor-arg>
<constructor-arg value=”红旗” index="o">constructor-arg>
<constructor-arg value="40000" index="2">constructor-arg>
bean>
property>
bean>
可以使用专用的元素标签为Bean的字符串或其他对象类型的属性注入null值
<property name="name ">
<null>null>
property>
<bean id="p2" class="edu.etime. springdemo.beans.Person">
<property name="name">
<null>null>
property>
<! --通过属性来应用其他bean -->
<property name="car">
<ref bean="car3" />
property>
<property name="car.price" value="40">property>
bean>
注意: Spring为级联属性赋值前必须先初始化对象,否则会出现异常.
<bean id="p3" class="edu.etime. springdemo.beans.Person">
<property name="name " value="张三">property>
<! --通过属性来应用其他bean -->
<! -- name="car ">
<bean class="edu.etime. springdemo.beans.car">
<constructor-arg value="大中国" index="1">constructor- arg>
<constructor- arg value="红旗"index="O">constructor-arg>
<constructor- arg value="40000" index="2">constructor-arg>
bean>
property> -->
<property name="car.price" value="44444">property>
bean>
如上所示:如果不先创建car这个属性,那么car.price就会出现异常
配置java.util.List类型的属性,需要指定标签,在标签里面包含一些元素,这些标签可以通过指定简单的常量值,通过指定对其他Bean的引用,通过指定内部Bean定义,通过指定空元素,甚至可以内嵌其他集合.
<bean id="th1" class= "edu.etime.springdemo.beans. TuHao">
<property name="name " value="上豪一号">property>
<property name="List">
<list>
<ref bean="car1"/>
<bean class="edu.etime.springdemo.beans.car">
<constructor-arg value="大中国" index="1">constructor-arg>
<constructor-arg value="红旗" index="0">constructor-arg>
<constructor-arg value="40000" index="2">constructor-arg>
bean>
list>
property>
bean>
<bean id="th2" class="edu.etime.springdemo.beans.TuHao">
<property name= "name" value="上豪er号">property>
<property name= "map">
<map>
<entry key="car1" value-ref="car1"/>
<entry key="car2" value-ref="car2"/>
map>
property>
bean>
使用定义 java.util.Properties,该标签使用多个作为子标签,每个标签必须定义key属性.
<! --注入properties -->
<bean id="datasource" class="edu.etime.springdemo. beans.Datasource">
<property name= "properties">
<props>
<prop key="driver">com.mysql.jdbc.Driverprop>
<prop key="url ">mysql:jdbc//127.0.0.1: 3306/textprop>
<prop key="username ">rootprop>
<prop key="password">123321234567prop>
props>
property>
bean>

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/spring-util.xsd">
util标签主要用于定义一些公用的集合,以供其他的bean来进行引用
<util:list id="list">
<ref bean="heLLo"/>
util:list>
<util:map id="map">
util:map>
<util:properties id="pro">
util:properties>

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd
http://www.springframework.org/schema/p
http://www.springframework.org/schema/spring-p.xsd">
作用: 为了简化配置(主要就是简化属性注入的配置)
<bean id="car0" class="edu.etime.springdemo.beans.car"
p:brand="红旗飘飘" p:corp="China" p:price="9999999">
bean>
Spring loc容器可以自动装配Bean.需要做的仅仅是在的 autowire 属性里指定自动装配的模式
byType (根据类型自动装配):若IoC容器中有多个与目标 Bean类型一致的 Bean.在这种情况下, Spring 将无法判定哪个Bean最合适该属性,所以不能执行自动装配.
byName (根据名称自动装配):必须将目标 Bean的名称和属性名设置的完全同.
constructor (通过构造器自动装配):当 Bean中存在多个构造器时,此种自动装配方式将会很复杂.不推荐使用
byType的Spring配置文件示例:
<bean id="car" class="edu.etime. springdemo2.beans.Car">
<property name="brand" value="红旗">property>
<property name="corp" value="中国">property><property name="price" value="599999">property>
bean>
<bean id="address" class="edu.etime.springdemo2.beans.Address ">
<property name="city" value="成都">property>
<property name="street" value="玉林路">property>
bean>
<bean id="person" class="edu.etime.springdemo2.beans.Person"autowire="byType">
<property name= "name" value="张三">property>
bean>
实体类:

注意: 使用byType进行自动装配,需要I0C容器中的同类型的bean只能有一个。如果同类型的bean有多个,这是Spring将无法识别是哪一个bean。将无法自动状态。
byName的Spring配置文件示例:
<bean id= "car" class= "edu.etime.springdemo2.beans.Car">
<property name= "brand" value= "红旗">property>
<property name= "corp" value= "中国">property>
<property name= "price" value="599999">property>
bean>
<bean id= "address1" class= "edu.etime.springdemo2.beans.Address">
<property name= "city" value= "成都">property>
<property name= "street”value= "玉林路">property>
bean>
<bean id= "address" class= "edu.etime.springdemo2.beans.Address ">
<property name= "city" value="北京">property>
<property name= "street" value= "长安街">property>
bean>
<bean id= "person" class= "edu. etime.springdemo2.beans.Person"
autowire= "byName ">
<property name= "name”value= "张三">property>
bean>
byName: 根据在Person类中所定义的属性名称进行自动装配,这个时候,需要类中的属性名称和配置文件中的bean的id–致方可进行自动装配。如果名称不一致,不能进行装配,
那么该属性的值为Null
在Bean配置文件里设置autowire属性进行自动装配将会装配Bean的所有属性.然
而,若只希望装配个别属性时,autowire属性就不够灵活了.
autowire属性 要么根据类型自动装配,要么根据名称自动装配,不能两者兼而有之.
一般情况下,在实际的项目中很少使用自动装配功能(配置文件中的自动装配),因为和
自动装配功能所带来的好处比起来,明确清晰的配置文档更有说服力一些
Spring允许继承bean 的配置。
继承仅仅是指配置上的继承,并不意味着这两个bean之间存在继承关系。继承bean配置仅仅是为了复用其配置信息。
子Bean 也可以覆盖从父Bean继承过来的配置
父Bean可以作为配置模板,也可以作为Bean实例.若只想把父Bean作为模板,可以设置 的abstract属性为true, 这样Spring 将不会实例化这个Bean
并不是元素里的所有属性都会被继承.比如: autowire, abstract 等.
也可以忽略父Bean的class 属性,让子Bean指定自己的类,而共享相同的属性配置.但此时abstract 必须设为true
<bean id= "address1" class= "edu.etime.springdemo2.beans.Address">
<property name= "city" value="成都">property>
<property name= "street" value= "玉林路">property>
bean>
<bean id= "address2" class="edu.etime.springdemo2.beans.Address "
parent= "address1">
bean>
<bean id= "address1" class="edu.etime.springdemo2.beans.Address">
<property name= "city" value= "成都" >property>
<property name= "street" value="玉林路">property>
bean>
<bean id= "address2" class="edu.etime.springdemo2.beans.Address"
parent= "address1">
<property- name= "street" value= "林阴街">property>
bean>
<bean id= "address1" class= "edu.etime.springdemo2.beans.Address" abstract="true">
<property name= "city" value="成都">property>
<property name= "street" value= "玉林路">property>
bean>
前置依赖 depends-on 不同与 ref 依赖。这两者都是表示对其他bean 的依赖,但是ref
常用的情况是这个bean作为当前bean的属性(依赖更直接)。
但是有时候依赖关系并不会这么明显,我们依赖的bean也许并不是我们当前bean 的
属性,比如当前bean GetConnection,我们需要初始化一些值,这些值的初始化是依赖于bean ConfigDataSource的,那么我们的bean GetConnection 肯定是依赖于ConfigDataSource的,但是ConfigDataSource并不是GetConnection的属性,这个时候用ref肯定是不合适的,就可以用depends-on
在Spring中,可以在元素的scope属性里面设置 Bean的作用域
默认情况下,Spring只为每个在IOC容器里面声明的Bean创建一个唯一 一个实例,整个IOC容器范围内部都嫩共享该实例: 所有后续的getBean()调用和Bean引用都将返回这个唯一的Bean实例.该作用域被称为singleton, 它是所有Bean的默认作用域.
| 类别 | 说明 |
|---|---|
| singleton | 在SpringIOC容器中仅存在一个Bean实例,Bean以单实例的方式存在 |
| prototype | 每次调用getBean()时都会返回一个新的实例 |
| request | 每次HTTP请求都会创建一个新的Bean,该作用域仅适合于WebApplicationContext环境 |
| session | 同一个HTTP Session共享一个Bean,不同的HTTPSession使用不同的Bean.该作用仅适合于WebApplicationContext环境 |
默认情况的配置文件:
<bean id= "address2" class="edu.etime.springdemo2.beans.Address"
parent= "address1" scope= "singleton">
<property name= "street" value= "林阴街">property>
bean>
在配置文件里配置Bean时,有时需要在Bean的配置里混入系统部署的细节信息(例如:文件路径,数据源配置信息等).而这些部署细节实际上需要和Bean 配置相分离
Spring提供了一个 PropertyPlaceholderConfigurer 的BeanFactory 后置处理器,这个处理器允许用户将Bean配置的部分内容外移到属性文件中.可以在Bean配置文件里使用形式${var} 的变量,PropertyPlaceholderConfigurer 从属性文件里加载属性,并使用这些属性来替换变量.

bean的生命周期:
bean的整个生命周期:
SpringI0C容器可以管理Bean的生命周期,Spring允许在Bean生命周期的特定点执
行定制的任务.
SpringIOC容器对Bean的生命周期进行管理的过程:
通过构造器或工厂方法创建Bean实例
为Bean 的属性设置值和对其他Bean的引用
调用Bean的初始化方法
Bean 可以使用了
当容器关闭时,调用Bean 的销毁方法
在Bean的声明里设置init-method 和destroy-method 属性,为Bean指定初始化和
销毁方法.
Bean生命周期
两个主要的生命周期方法:
① init-method 初始化方法
② destory-method 销毁方法
Bean 的整个生命周期其

Bean后置处理器允许在调用初始化方法前后对Bean进行额外的处理.
Bean 后置处理器对IOC容器里的所有Bean 实例逐一处理, 而非单-实例.其典型应用是:检查Bean属性的正确性或根据特定的标准更改Bean的属性.
对Bean后置处理器而言,需要实现BeanPostProcessor接口.在初始化方法被调用前后,Spring将把每个Bean 实例分别传递给.上述接口的以下两个方法:
postProcessBeforeInitialization
postProcessAfterInitialization
租价你扫面(component scanning) : spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件
特定组件包括:
@Component: 基本注解,标识了一个受Spring 管理的组件
@Repository: 标识持久层组件
@Service: 标识服务层(业务层)组件
@Controller: 标识表现层组件
上面4中注解的作用是一样的,都是在告诉spring,请把这个类放入到IOC容器中。而这几个注解的区别仅仅只是用于区别不同组件在程序中的作用。
对于扫描到的组件, Spring有默认的命名策略:使用非限定类名,第-一个字母小写.也可以在注解中通过value属性值标识组件的名称。(如果没有指定扫描到的组件的名称,那么默认使用类名作为组件的名称,第 一个字母小写)
自动扫描步骤:
面试常问的问题:
区别:




@Autowired
@Autowired 通过byType方式进行自动装配 @Resource 通过byName方式进行自动装配,可以理解是xml的setter方式注入方式
组件装配
context:component-scan 元素还会自动注册AutowiredAnnotationBeanPostProcessor实例,该实例可以自动装配具有@Autowired 和@Resource 、@Inject 注解的属性。
说明:上面三个注解的作用几乎相同的。一般使用@autowired注解
autowired 注解
@Autowired注解自动装配具有兼容类型的单个Bean 属性。(首先使用类型进行匹配,如果类型的bean有多个,那么再采用名称进行匹配,如果名称匹配不上,那么就会抛出异常)
构造器,普通字段(即使是非public),一切具有参数的方法都可以应用@Autowired注解
默认情况下,所有使用@Autowired 注解的属性都需要被设置.当Spring 找不到匹配的Bean 装配属性时,会抛出异常,若某一属性允许不被设置,可以设置@Autowired 注解的required 属性为false
默认情况下,当I0C容器里存在多个类型兼容的Bean时,通过类型的自动装配将无法工作。如果ioc容器中包含多个兼容类型的bean,那么@AutoWired注解还会根据变量名与bean的名称进行自动装配。
@Autowired注解也可以应用在数组类型的属性.上,此时Spring将会把所有匹配的Bean进行自动装配
@Autowired注解也可以应用在集合属性上,此时Spring 读取该集合的类型信息,然后自动装配所有与之兼容的Bean.
@Autowired注解用在java.util.Map. 上时, 若该Map的键值为String, 那么Spring将自动装配与之Map值类型兼容的Bean,此时Bean的名称作为键值

