1.什么是Spring
- Spring是一个轻量级的IOC和AOP容器框架,解决了企业应用开发的复杂度。从简单性,可测试性,松耦合来说,所有的Java程序都可以从中受益。
2.Spring的好处
- Spring属于低侵入式设计,代码的污染极低。
- Spring的DI机制降低了业务对象替换的复杂性。
- 降低了组件之间的耦合度,实现了软件各层之间的解耦。
- Spring的AOP技术(面向切面编程),可以很轻松的实现权限拦截,运行期监控等功能。
- 容器提供单例模式。
- Spring可以和其他框架完美的融合,加快了应用的开发。
3.Spring中IOC和DI的理解
- IOC:inversion of control,控制反转,把创建对象的权力交给Spring容器,使相互协作的各个组件之间相互解耦。
- DI:dependency injection,依赖注入,主动把被调用者的属性或依赖对象注入给被调用者。
- 理解:DI可以说是一种思想,而IOC则是一种结果。当使用一个对象的时候,想要调用和它关联的另外对象的时候,以前我们需要之间new对象才能调用,就像service需要dao,controller需要service,但是这样new对象就会使各个组件之间的耦合度增加,我们就会想能不能不new对象,依赖其他方式注入给我,这时依赖注入的思想就出现了,使用依赖注入的结果就是导致对象控制权的转移,也就是控制反转IOC。
4.Spring中支持Bean的几个作用域
Spring中Bean的作用域一共有5个分别是:、
- singleton:单例,这种Bean范围是默认的,不管收到多少次请求,容器中只有一个Bean,这种单例模式有BeanFactory自身维护
- prototype:多例,和单例相反,每一个Bean请求都会创建一个新的对象
- request:每一个来自网络端的客户请求都会创建一个对象,作用范围是一次请求,请求结束,对象死亡。
- session:每一个Session中有一个对象实例,Session失效,对象也随之失效。
- global-session:global-session和Portlet应用相关,global-session和session的作用范围相同。
5.Bean的生命周期和作用范围
- 单例对象:singleton,整个程序中只有一个对象,作用范围是整个程序。在容器创建之前就实例化到工厂里面,只要容器还在就一直存活,单例模式有一个lazy-init(懒加载),如果lazy-init开启,那么当第一次使用该对象的时候才创建对象。
1:出生:取决于lazy-init,如果懒加载没有开启,那么容器创建时就创建对象。如果懒加载开启,那么在第一次使用对象的时候创建。
2:活着:只要容器在,那么对象就一直活着。
3:死亡:容器被销毁的时候,对象也就死亡了。 - 多例对象:prototype,
1:出生:当使用对象时就创建一个对象。
2:活着:多例和懒加载无关,只要对象在是使用中就一直活着
3:死亡:如果对象长时间不使用,那么就会被垃圾回收机制回收,这时对象死亡。
6.创建Bean的方式
- 使用默认无参构造函数
<!--在默认情况下:
它会根据默认无参构造函数来创建类对象。如果 bean 中没有默认无参构造函数,将会创建失败。
如果你没有写无参构造,java编译器会为你自动创建一个无参构造
-->
<bean id="Stu" class="com.fml.bean.Student" />
- spring 管理静态工厂-使用静态工厂的方法创建对象
/**
* 模拟一个静态工厂,创建业务层实现类
*/
public class StaticFactory {
public static IAccountService createAccountService(){
return new AccountServiceImpl();
}
}
<!--
通过class获得静态工厂 通过factory-method来调用静态工厂的createPerson方法
-->
<!-- 此种方式是:
使用 StaticFactory 类中的静态方法 createAccountService 创建对象,并存入 spring 容器
id 属性:指定 bean 的 id,用于从容器中获取
class 属性:指定静态工厂的全限定类名
factory-method 属性:指定生产对象的静态方法
-->
<!--使用静态工厂创建对象-->
<bean id="p2" class="com.bruceliu.factory.PersonFactory" factory-method="createPerson"/>
- spring 管理实例工厂-使用实例工厂的方法创建对象
/**
* 模拟一个实例工厂,创建业务层实现类
* 此工厂创建对象,必须现有工厂实例对象,再调用方法
*/
public class InstanceFactory {
public IAccountService createAccountService(){
return new AccountServiceImpl();
}
}
<!-- 此种方式是:
先把工厂的创建交给 spring 来管理。
然后在使用工厂的 bean 来调用里面的方法
factory-bean 属性:用于指定实例工厂 bean 的 id。
factory-method 属性:用于指定实例工厂中创建对象的方法。
-->
<bean id="instancFactory" class="com.bruce.factory.InstanceFactory"></bean>
<bean id="accountService"
factory-bean="instancFactory"
factory-method="createAccountService">
</bean>
7.依赖注入
- 依赖注入的概念
依赖注入:Dependency Injection。它是 spring 框架核心 ioc 的具体实现。
我们的程序在编写时,通过控制反转,把对象的创建交给了 spring,但是代码中不可能出现没有依赖的情况。ioc 解耦只是降低他们的依赖关系,但不会消除。例如:我们的业务层仍会调用持久层的方法。
那这种业务层和持久层的依赖关系,在使用 spring 之后,就让 spring 来维护了。
简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。 - 构造函数注入
public class AccountServiceImpl implements IAccountService {
private String name;
private Integer age;
private Date birthday;
public AccountServiceImpl(String name, Integer age, Date birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
@Override
public void saveAccount() {
System.out.println(name+","+age+","+birthday);
}
}
<!-- 使用构造函数的方式,给 service 中的属性传值
要求:
类中需要提供一个对应参数列表的构造函数。
涉及的标签:
constructor-arg
属性:
index:指定参数在构造函数参数列表的索引位置
type:指定参数在构造函数中的数据类型
name:指定参数在构造函数中的名称 用这个找给谁赋值
=======上面三个都是找给谁赋值,下面两个指的是赋什么值的==============
value:它能赋的值是基本数据类型和 String 类型
ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean-->
<bean id="accountService" class="com.bruceliu.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>```
- set 方法注入
public class AccountServiceImpl implements IAccountService {
private String name;
private Integer age;
private Date birthday;
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public void saveAccount() {
System.out.println(name+","+age+","+birthday);
}
}
<!-- 通过配置文件给 bean 中的属性传值:使用 set 方法的方式
涉及的标签:
property
属性:
name:找的是类中 set 方法后面的部分
ref:给属性赋值是其他 bean 类型的
value:给属性赋值是基本数据类型和 string 类型的
实际开发中,此种方式用的较多。
-->
<bean id="accountService" class="com.bruce.service.impl.AccountServiceImpl">
<property name="name" value="test"></property>
<property name="age" value="21"></property>
<property name="birthday" ref="now"></property>
</bean>
<bean id="now" class="java.util.Date"></bean>
- 注入集合属性
顾名思义,就是给类中的集合成员传值,它用的也是set方法注入的方式,只不过变量的数据类型都是集合。我们这里介绍注入数组,List,Set,Map,Properties。具体代码如下:
public class AccountServiceImpl implements IAccountService {
private String[] myStrs;
private List<String> myList;
private Set<String> mySet;
private Map<String,String> myMap;
private Properties myProps;
public void setMyStrs(String[] myStrs) {
this.myStrs = myStrs;
}
public void setMyList(List<String> myList) {
this.myList = myList;
}
public void setMySet(Set<String> mySet) {
this.mySet = mySet;
}
public void setMyMap(Map<String, String> myMap) {
this.myMap = myMap;
}
public void setMyProps(Properties myProps) {
this.myProps = myProps;
}
@Override
public void saveAccount() {
System.out.println(Arrays.toString(myStrs));
System.out.println(myList);
System.out.println(mySet);
System.out.println(myMap);
System.out.println(myProps);
}
}```
```handlebars
<!-- 注入集合数据
List 结构的:
array,list,set
Map 结构的
map,entry,props,prop
-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<!-- 在注入集合数据时,只要结构相同,标签可以互换 -->
<!-- 给数组注入数据 -->
<property name="myStrs">
<set>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</set>
</property>
<!-- 注入 list 集合数据 -->
<property name="myList">
<array>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</array>
</property>
<!-- 注入 set 集合数据 -->
<property name="mySet">
<list>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</list>
</property>
<!-- 注入 Map 数据 -->
<property name="myMap">
<props>
<prop key="testA">aaa</prop>
<prop key="testB">bbb</prop>
</props>
</property>
<!-- 注入 properties 数据 -->
<property name="myProps">
<map>
<entry key="testA" value="aaa"></entry>
<entry key="testB">
<value>bbb</value>
</entry>
</map>
</property>
</bean>```