前言
maven引入
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.4.RELEASE</version>
</dependency>
bean定义?
?基本的几个属性值有id、name、class
id是唯一指定标识,name可以有多个,class指定bean类型
<bean id="person" name="n1,n2,n3" class="com.baizhiedu.basic.Person" scope="singleton"></bean>
如果是web服务,IOC容器类型为XmlWebApplicationContext,我是在测试环境下,用ClassPathXmlApplicationContext
Person类
@Data
@AllArgsConstructor
public class Person {
public Person(){
System.out.println("new Persong");
}
private String name;
private int age;
private String password;
private void init(){
System.out.println("init");
}
private void destroy(){
System.out.println("destroy"+age);
}
}
?测试代码
@Test
public void test1(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("/applicationContext.xml");
// Person p = (Person)ioc.getBean(id|name); 可以根据bean的id、name获取bean实例
Person p1 = (Person)ioc.getBean("person");
Person p2 = (Person)ioc.getBean("n1");
System.out.println(p1.toString());
p1.setAge(10);
System.out.println(p2.toString());
}
scope?
1、scope类型
在Spring 2.0之前,有singleton和prototype两种;
在Spring 2.0之后,为支持web应用的ApplicationContext,增强另外三种:request,session和global session类型,它们只实用于web程序,通常是和XmlWebApplicationContext共同使用。
1、singleton?
此取值时表明容器中创建时只存在一个实例,所有引用此bean都是单一实例。如同每个国家都有一个总统,国家的所有人共用此总统,而这个国家就是一个spring容器,总统就是spring创建的类的bean,国家中的人就是其它调用者,总统是一个表明其在spring中的scope为singleton,也就是单例模型。
此外,singleton类型的bean定义从容器启动到第一次被请求而实例化开始,只要容器不销毁或退出,该类型的bean的单一实例就会一直存活,典型单例模式,如同servlet在web容器中的生命周期。
? ?单例情况下: ?不能使用共享成员变量 ?, ?在并发情况下本来是true , 但另一线程进来 , 变为false , ?期望结果是true , 并发会导致数据不准确
2、prototype
请求方spring容器在进行输出prototype的bean对象时,会每次都重新生成一个新的对象,虽然这种类型的对象的实例化以及属性设置等工作都是由容器负责的,但是只要准备完毕,并且对象实例返回给请求方之后,容器就不在拥有当前对象的引用,请求方需要自己负责当前对象后继生命周期的管理工作,包括该对象的销毁。也就是说,容器每次返回请求方该对象的一个新的实例之后,就由这个对象“自生自灭”,最典型的体现就是spring与struts2进行整合时,要把action的scope改为prototype。
?属性值为prototype时 , 并发时线程是安全的
如同分苹果,将苹果的bean的scope属性声明为prototype,在每个人领取苹果的时候,我们都是发一个新的苹果给他,发完之后,别人爱怎么吃就怎么吃,爱什么时候吃什么时候吃,但是注意吃完要把苹果核扔到垃圾箱!对于那些不能共享使用的对象类型,应该将其定义的scope设为prototype。
3、request
再次说明request,session和global session类型只实用于web程序,通常是和XmlWebApplicationContext共同使用。 <bean id ="requestPrecessor" class="...RequestPrecessor" ? scope="request" />
Spring容器,即XmlWebApplicationContext 会为每个HTTP请求创建一个全新的RequestPrecessor对象,当请求结束后,该对象的生命周期即告结束,如同java web中request的生命周期。当同时有100个HTTP请求进来的时候,容器会分别针对这10个请求创建10个全新的RequestPrecessor实例,且他们相互之间互不干扰,简单来讲,request可以看做prototype的一种特例,除了场景更加具体之外,语意上差不多。
4、session
对于web应用来说,放到session中最普遍的就是用户的登录信息,对于这种放到session中的信息,我们可以使用如下形式的制定scope为session:
<bean id ="userPreferences" class="...UserPreferences" ? scope="session" />
Spring容器会为每个独立的session创建属于自己的全新的UserPreferences实例,比request scope的bean会存活更长的时间,其他的方面没区别,如果java web中session的生命周期。
5、global session
<bean id ="userPreferences" class="...UserPreferences" ? scope="globalsession" />
global session只有应用在基于porlet的web应用程序中才有意义,它映射到porlet的global范围的session,如果普通的servlet的web 应用中使用了这个scope,容器会把它作为普通的session的scope对待。
总结
| 取值范围 | 说明 |
|---|
| singleton | 单例,并发情况线程不安全,应用时需要volatile 生命周期: 随着ioc创建而创建 ioc容器会一直拥有此bean的引用以保证不被回收 随着ioc卸载而消亡 | | prototype | 多例,影响效率,并发情况线程安全 生命周期: 随着线程调用getBean()而创建 ioc容器不会拥有此bean的引用,也就是说ioc只管出生,不管消亡,靠gc回收 | | request | web环境下,为每个requset创建独立bean,生命周期同prototype | | session | web环境下,为每个session创建独立bean,即存在于session域中,存活时间比request有所提升,生命周期同prototype | | global session | web环境下,应用在portlet环境,如果没有portlet环境会被当作session,生命周期同prototype |
2、scope配置
1、xml方式
进行bean的配置时,指定scope。

2、注解方式
前提为配置spring为注解配置。

?初始化、销毁方法
init-method和destroy-method,如下,init和destroy均是Person类的方法,当bean被实例化后会执行init-method绑定的方法,当ioc容器销毁时,会执行destroy-method绑定的方法
<bean id="person" name="n1,n2,n3" class="com.baizhiedu.basic.Person" init-method="init" destroy-method="destroy"></bean>?

工厂创建
1、无参构造创建
之前的bean定义均是无参构造的应用
2、静态工厂方法创建
此时bean里加上一个静态方法 getFighterInstance1,一个实例方法getFighterInstance2
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Fighter {
public static Fighter getFighterInstance1(){
return new Fighter();
}
public Fighter getFighterInstance2(){
return new Fighter(10,"J-20","A");
}
// 服役年限
private int age;
// 战机名称
private String name;
// 战机型号
private String model;
}
然后applicationContext.xml中通过factory-method来创建
<bean id="fighter1" class="com.baizhiedu.basic.Fighter" factory-method="getFighterInstance1"></bean>
3、成员方法创建
这个也简单,是指用一个bean实例的方法来创建另一个bean
//基于上面的fighter1来执行
<bean id="fighter2" class="com.baizhiedu.basic.Fighter" factory-bean="fighter1" factory-method="getFighterInstance2"></bean>
【注:】
利用方法来创建实例是非常常见的,如DriverManager创建connector实例
依赖注入 Dependency Injection
1、概念
编写程序时,通过控制反转把对象的创建交给spring,但是代码中不可能出现无依赖的情况。
IOC解耦只是降低他们的依赖关系,但不会消除。如service层调用dao层
2、注入方法
首先因示例关系加入一个class,后面会用
@Data
@AllArgsConstructor
@NoArgsConstructor
public class FighterService {
private Fighter fighter;
public Fighter create(){
fighter.setAge(0);
fighter.setModel("C");
return fighter;
}
}
1、构造器注入
<!-- 实例方法创建实例-->
<bean id="fighter2" class="com.baizhiedu.basic.pojo.Fighter" factory-bean="fighter1" factory-method="getFighterInstance2"></bean>
<!-- 构造器注入-->
<bean id="fighterService1" class="com.baizhiedu.basic.service.FighterService" >
<constructor-arg name="fighter" ref="fighter2"></constructor-arg>
</bean>
2、set注入
- 普通数据类型
- 引用数据类型
- 集合数据类型
【注:】set注入时的property标签的name值是set方法的部分内容,例如setUrl,那么name值为url,即去掉set后首字母大写,我之前一直以为name值是变量值,结果用jdcbUrl错了半天


切分配置文件
即主配置文件会引入其它多分配置文件,目的是方便功能区分
1、创建一个分文件

2、beans标签导入
xmlns:p="http://www.springframework.org/schema/p"

?3、导入分文件

?Spring相关API
applicationContext
接口类型,代表应用上下文,可以通过其实例获得spring容器中的Bean

getBean()
下面代码是ClassPathXmlApplicationContext的顶级父类AbstractApplicationContext定义的
public Object getBean(String name) throws BeansException {
this.assertBeanFactoryActive();
return this.getBeanFactory().getBean(name);
}
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
this.assertBeanFactoryActive();
return this.getBeanFactory().getBean(name, requiredType);
}
public Object getBean(String name, Object... args) throws BeansException {
this.assertBeanFactoryActive();
return this.getBeanFactory().getBean(name, args);
}
public <T> T getBean(Class<T> requiredType) throws BeansException {
this.assertBeanFactoryActive();
return this.getBeanFactory().getBean(requiredType);
}
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
this.assertBeanFactoryActive();
return this.getBeanFactory().getBean(requiredType, args);
}
?从中发现getBean()根据id、name、反射类等属性来获取Bean,其中根据反射类获取必须要求IOC容器中对应类型的bean有且只有一个
实战——Spring配置数据源
maven
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.4</version>
</dependency>
配置1:jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.0.2:3306/test1
jdbc.account=root
jdbc.password=961003
配置2: applicationContext.xml
其中为了支持导入properties,添加了context依赖

bean调用引入的context依赖?
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
>
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName">
<value>${jdbc.driver}</value>
</property>
<property name="url">
<value>jdbc:mysql://192.168.0.2:3306/test1</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>961003</value>
</property>
</bean>
</beans>
?测试
@Test
public void test2(){
// 基于spring启动druid
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
DruidDataSource dataSource = (DruidDataSource) ioc.getBean("datasource");
System.out.println(dataSource.toString());
}
Spring注解开发

|