Spring基本特征
Spring以一种非侵入式的方式来管理你的代码
侵入式方式(例如hibernate,struts):必须了解框架内部如何运作的,代码才好些
非侵入式方式(例如Spring):不需要了解内部如何运作,但可以使用
spring容器分为两大类:
1、可配置的容器
ClassPathXmlApplicationContext
FileSystemXmlApplicationContext
2、web容器
WebApplicationContext
1、springIOC
1、概念
把对象的创建、初始化、销毁等工作交给spring容器来做
2、好处:程序员不必再关心对象的创建,更专注业务逻辑
3、前提条件:spring中的bean必须是单例模式
4、细节:
1、对象创建的方式:(alias是起别名的方式,不管其多少个别名,调用多少次,都只有单例的类)
1、利用默认的构造函数创建
public class HelloWorld { public void hello(){ System.out.println("Hello world"); } } |
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="helloWorld" class="com.itheima.bean.HelloWorld"></bean> <alias name="helloWorld" alias="狗蛋"/> <alias name="helloWorld" alias="二狗蛋"></alias> </beans> |
2、静态工厂方法创建
工厂类:
public class HelloWorldFactory { public static Object getInstance(){ return new HelloWorld(); } } |
配置文件:
<bean id="helloWorld2" class="com.itheima05.spring.bean.HelloWorldFactory" factory-method="getInstance" /> |
3、实例工厂方法创建
工厂类中:
|
配置文件中:
<bean id="helloWorld3" class="com.itheima05.spring.bean.HelloWorldFactory2"/> <!-- spring容器为HelloWorldFactory2创建对象--> <bean id="helloWorldFactory" factory-bean="helloWorld3" factory-method="getInstance"/> |
4、创建对象的时机
1、在默认的情况下,在spring容器启动的时候创建对象
在spring配置文件中,只要根据以上的三种方式的其中一种配置了,spring容器就会创建对象
好处:spring容器和web容器整合的时候,当web容器启动的时候就可以初始化spring容器了,如果这个时候
spring容器内部有错误,则直接会报错
如果该bean中存放着大量的数据,而且数据的初始化发生在创建对象的时候,这个时候,数据会过早的驻留在内存中
2、如果在spring的配置文件中一个bean的配置中有lazy-init="true",那么该bean在调用getBean方法时创建对象
不好处:不能过早的发现错误
好处:按照需求加载数据(什么时候要什么时候加载)
<bean id="helloWorld" class="com.itheima05.spring.bean.HelloWorld" lazy-init="true"/> <bean id="helloWorld2" class="com.itheima05.spring.bean.HelloWorldFactory" factory-method="getInstance" lazy-init="true"/> <bean id="helloWorld3" class="com.itheima05.spring.bean.HelloWorldFactory2"/> <bean id="helloWorldFactory" factory-bean="helloWorld3" factory-method="getInstance" lazy-init="true"/> |
5、对象的scope
1、在默认的情况下,是单例模式
2、scope="prototype"为多实例
不管lazy-init为什么值,都是getBean时才要创建该对象
<bean id="helloWorld" class="com.itheima05.spring.bean.HelloWorld" scope="prototype"/> |
6、init方法
1、在java代码中声明init方法
2、在spring的配置文件中进行配置init-method="init"
3、在创建完成该bean的对象的时候,spring会自动调用init方法
4、可以在该方法中做一些初始化的工作
以下配置destroy不会执行
<bean id="helloWorld" class="com.itheima05.spring.bean.HelloWorld" init-method="init" destroy-method="destroy" scope="prototype"></bean> |
7、destroy方法
当spring容器关闭的时候,调用该方法
配置
1、在java代码中声明destroy方法
2、在spring的配置文件中进行配置destroy-method="destroy"
如果该bean为scope="prototype",spring容器不负责销毁
|
2、springDI
1、概念
给spring管理的对象的属性赋值
|
2、赋值方式
1、利用set方法可以实现赋值
步骤
1、写一个bean,该bean中有属性,并且提供属性的setter方法
2、在spring的配置文件中利用<property name="pid"value="1"></property>给属性赋值
如果是一般属性(基本类型和String类型),则用value赋值
如果是引用属性,则用ref赋值
spring容器做的事情:
1、启动spring容器
2、为bean创建对象
3、调用set方法为属性赋值
<bean id="person" class="com.itheima05.spring.bean.Person"> <property name="name" value="徐若瑄"></property> <property name="student" ref="student"></property> <property name="list"> <list> <value>list1</value> <value>list2</value> <ref bean="student"/> </list> </property> <property name="set"> <set> <value>set1</value> <value>set2</value> <ref bean="student"/> </set> </property> <property name="map"> <map> <entry key="m1"> <value>map1</value> </entry> <entry key="m2"> <value>map2</value> </entry> <entry key="m3"> <ref bean="student"/> </entry> </map> </property> </bean> <bean id="student" class="com.itheima05.spring.bean.Student"></bean> |
2、利用构造器可以实现赋值
如果在配置文件中,一个bean含有元素constructor-arg,那么将用指定的构造器创建对象,这个时候可以利用构造器赋值
constructor-arg代表的是构造器的参数
index 下标
type 类型
value 一般属性的值
ref 引用类型的值
一个bean只能配置一个构造器
注意:构造函数可以重载,配置文件的参数可以全部打开,以最后出现的一组参数为准,前面的参数会被覆盖。如果最后一组参数和任意构造函数参数不符,则报错
<bean id="person" class="com.itheima05.spring.bean.Person"> <!-- <constructor-arg index="0" value="aaa"></constructor-arg> <constructor-arg index="1" ref="student"></constructor-arg> --> <constructor-arg index="0" value="4"></constructor-arg> <constructor-arg index="1" value="afdsads"></constructor-arg> </bean> <bean id="student" class="com.itheima05.spring.bean.Student"></bean> |
3、springIOC和DI的意义
在一个类中引用了一个属性:接口,在java代码端可以不用为该接口实现了,这个事情由spring容器来完成,客户端只需要面向接口编程即可
注意一下例子是两种注入方式,任意一种都可以实现
//可以利用set方法注入 public void setDocument(Document document) { this.document = document; } //利用构造器注入 public DocumentManager(Document document){ this.document = document; } |
<bean id="excelDocument" class="com.itheima05.document.ExcelDocument"></bean> <bean id="pdfDocument" class="com.itheima05.document.PDFDocument"></bean> <bean id="wordDocument" class="com.itheima05.document.WordDocument"></bean> <bean id="documentManager" class="com.itheima05.document.DocumentManager"> <property name="document"> <ref bean="wordDocument"/> </property> <constructor-arg index="0" ref="wordDocument"></constructor-arg> </bean> |
MVC依赖注入例子
public interface Dao { public void save(); } |
public class DaoImpl implements Dao { public void save() { System.out.println("save dao"); } } |
public interface Service { public void save(); } |
public class ServiceImpl implements Service { Dao dao; public void setDao(Dao dao) { this.dao = dao; } public void save() { this.dao.save(); } } |
public class Action { Service service; public void setService(Service service) { this.service = service; } public void save(){ this.service.save(); } } |
<bean name="dao" class="com.itheima.mvc.DaoImpl"></bean> <bean name="service" class="com.itheima.mvc.ServiceImpl"> <property name="dao"> <ref bean="dao"/> </property> </bean> <bean name="action" class="com.itheima.mvc.Action"> <property name="service"> <ref bean="service"/> </property> </bean> |
注解: 引用类型可以用注解,其他类型不可以使用
步骤:启动spring容器
1、spring容器为所有的bean创建对象
2、当spring容器解析到
<context:annotation-config></context:annotation-config>
3、启动依赖注入的注解解析器,会在spring管理的bean中寻找所有的属性
看属性上是否有@Resource
4、如果该属性上有注解
注解的name属性的值为""
让注解所在的属性的名称和spring容器中的id进行匹配,如果匹配成功,则赋值,如果匹配不成功,则按照类型进行匹配,
如果匹配成功,则赋值,如果再匹配不成功,则报错
注解的name属性的值不为""
让name属性的值和spring容器中的id进行匹配,如果成功,则赋值,如果不成功,则报错
注意加入context约束
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> |
<context:annotation-config></context:annotation-config> <bean id="person" class="com.itheima05.spring.bean.Person"></bean> <bean id="student" class="com.itheima05.spring.bean.Student"></bean> |
import javax.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; public class Person { @Resource(name="student1")//以下两条等同于此条 //@Autowired//按照类型进行匹配 //@Qualifier("student") private Student student; public void hello(){ this.student.student(); } } |
4、注解
1、依赖注入的注解
1、步骤
1、在spring的配置文件中引入该命名空间context
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> |
2、启动依赖注入的注解解析器(base-package在该包及子包下扫描)
<context:component-scan base-package="com.itheima05.spring.bean"> </context:component-scan> |
3、在一个类的属性上标注@Resource注解
2、原理
见PPT
2、类扫描的注解
1、步骤
1、引入命名空间
<context:component-scan base-package="com.itheima05.spring.document.annotation"> </context:component-scan> |
2、启动注解解析器
@Component("documentManager") public class DocumentManager { @Resource(name="wordDocument") private Document document; public void read(){ this.document.read(); } public void write(){ this.document.write(); } } |
3、在类上加@Component,@Service,@Controller,@Repository
@Service用于标注业务层组件,
@Controller用于标注控制层组件(如struts中的action),
@Repository用于标注数据访问组件,即DAO组件,
@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
<context:component-scan base-package="com.itheima05.spring.mvc.annotation"> </context:component-scan> |
@Controller public class PersonAction { @Resource private PersonService personService; public void savePerson(){ this.personService.savePerson(); } } |
@Service("personService") public class PersonServiceImpl implements PersonService{ @Resource private PersonDao personDao; public void savePerson() { this.personDao.savePerson(); } } |
@Repository("personDao") public class PersonDaoImpl implements PersonDao{ public void savePerson() { System.out.println("save person"); } } |
2、原理
见PPT
扩展
继承类
<!-- abstract spring容器不会再为该bean创建对象 --> <bean id="person" class="com.itheima05.spring.extend.Person" abstract="true"> <property name="s" value="aaa"></property> </bean> <!-- parent 让student拥有person中的内容 --> <bean id="student" class="com.itheima05.spring.extend.Student" parent="person"></bean> |
public class Person { private String s; public void setS(String s) { this.s = s; } } public class Student extends Person{ } |