简介:本笔记主要介绍以下几点
1、Bean的常见属性及其子元素
2、实例化Bean的三种方式
3、Bean的生命周期和作用域
4、Bean的三种装配方式
1、Bean的配置
Spring简单来说就是一个大工厂,这个工厂负责创建和管理Spring容器中的Bean对象,如果要使用,就需要对其进行配置。
Spring支持XML和Properties两种格式的配置文件。(常用的是XML方式,便于管理Bean和Bean之间的关系)。
XML配置方式根元素是<beans>
<beans>
中包含多个<bean>
子元素。
1、<bean>
元素的常见属性及子元素
属性或子元素名称 | 解释 |
---|---|
id | 是每一个Bean的唯一标识,Spring容器对Bean的配置,管理都需要靠该属性来完成 |
name | Spring容器可以通过name属性来对Bean进行管理和配置,此时name可以被配置多个,多个值之间使用逗号隔开 |
class | 该属性指定Bean的具体实现类,必须填写全限定类名。 |
constructor-arg | <bean> 元素的子元素,可以使用此元素传入构造器的参数进行实例化。该元素的index属性指定构造参数的序号(从0)开始,type属性指定狗仔参数的类型,参数值可以通过ref属性或value直接指定 |
property | <bean> 元素的子元素,用于调用bean实例中的setter方法完成属性赋值,从而完成依赖注入。该元素的name指定实例中相应的属性名称,ref或value用于指定参数值 |
ref | <property> <constructor-arg > 等元素的属性或子元素,可以用于指定工厂中某个Bean的实例引用 |
value | <property> <constructor-arg > 等元素的属性或子元素,可以用于指定一个常量值 |
list | 用于封装List或数组类型的依赖注入 |
set | 用于封装set类型的依赖注入 |
map | 用于封装map类型的依赖注入 |
entry | <map> 元素的子元素,用于设置一个键值对,其中key属性标识键值,ref或value表示值。 |
2、基本使用演示
<?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: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/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--关联db.properties-->
<context:property-placeholder location="classpath:db.properties"/>
<!--配置数据库连接池-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${password}"/>
</bean>
<!--配置StudentDAOImpl-->
<bean id="studentDAO" class="cn.simplelife.dao.impl.StudentDAOImpl">
<property name="dataSource" ref="druidDataSource"/>
</bean>
<!--配置serviceImpl-->
<bean id="studentService" class="cn.simplelife.service.impl.StudentServiceImpl">
<property name="studentDAO" ref="studentDAO"/>
</bean>
</beans>
【注意】:
如果id和name属性都没有指定,那么spring会默认将class的值当作id使用
2、Bean的实例化
在java中我们需要使用一个对象的时候,就必须先实例化这个对象,Spring中也是如此。Spring中实例化的方式主要有以下三种:
1、构造器实例化
2、静态工厂实例化
3、实例工厂实例化
1、构造器实例化
1、创建一个Cat类
package cn.simplelife.domain;
/**
* @ClassName Cat
* @Description
* @Author simplelife
* @Date 2022/11/18 9:54
* @Version 1.0
*/
public class Cat {
}
2、书写一个配置文件
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
<bean id="cat" class="cn.simplelife.domain.Cat"/>
</beans>
3、编写测试类
package cn.simplelife.domain;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.*;
/**
* @ClassName CatTest
* @Description
* @Author simplelife
* @Date 2022/11/18 9:55
* @Version 1.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:cat.xml")
public class CatTest {
@Autowired
private Cat cat;
@Test
public void getCat() {
System.out.println(cat);
}
}
4、运行截图
2、静态工厂方式实例化
1、创建一个Duck类
package cn.simplelife.domain;
/**
* @ClassName Duck
* @Description
* @Author simplelife
* @Date 2022/11/21 17:20
* @Version 1.0
*/
public class Duck {
}
2、创建一个静态工厂类
package cn.simplelife.domain;
/**
* @ClassName DuckFactoryBean
* @Description
* @Author simplelife
* @Date 2022/11/21 17:21
* @Version 1.0
*/
public class DuckFactoryBean {
public static Duck createDuck() {
return new Duck();
}
}
3、书写配置文件
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
<bean id="duck" class="cn.simplelife.domain.DuckFactoryBean" factory-method="createDuck"/>
</beans>
4、编写测试类
package cn.simplelife.domain;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ClassName DuckFactoryBeanTest
* @Description
* @Author simplelife
* @Date 2022/11/21 17:25
* @Version 1.0
*/
public class DuckFactoryBeanTest {
@Test
public void getDuck(){
ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("classpath:duck.xml");
Duck bean = classPathXmlApplicationContext.getBean(Duck.class);
System.out.println("bean = " + bean);
}
}
5、运行截图
3、实例工厂方式实例化
1、创建一个Dog类
package cn.simplelife.domain;
/**
* @ClassName Dog
* @Description
* @Author simplelife
* @Date 2022/11/18 9:59
* @Version 1.0
*/
public class Dog {
}
2、创建一个实例工厂用来返回Dog对象
package cn.simplelife.domain;
/**
* @ClassName DogFactory
* @Description
* @Author simplelife
* @Date 2022/11/18 9:59
* @Version 1.0
*/
public class DogFactoryBean {
public Dog createDog() {
return new Dog();
}
}
3、书写配置文件
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
<!--配置实例工厂-->
<bean id="dogFactoryBean" class="cn.simplelife.domain.DogFactoryBean"/>
<!--配置dog实例
factory-bean="dogFactoryBean":使用配置的实例工厂
factory-method="createDog":使用工厂中的方法创建对象
-->
<bean id="dog" factory-bean="dogFactoryBean" factory-method="createDog"/>
</beans>
4、编写测试类
package cn.simplelife.domain;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ClassName DogTest
* @Description
* @Author simplelife
* @Date 2022/11/18 10:00
* @Version 1.0
*/
public class DogTest {
@Test
public void testGetDog() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:dog.xml");
Dog bean = applicationContext.getBean(Dog.class);
System.out.println("bean = " + bean);
}
}
5、运行截图
3、Bean的作用域
1、Spring中Bean对象的作用域分类
作用域名称 | 说明 |
---|---|
singleton | 使用该作用域,那么从始至终都只有一个实例对象存在于容器中,也是spring容器的默认的作用域 |
prototype | 每次通过Spring容器获取的prototype定义的bean,Spring容器都会创建一个新的bean实例对象,该对象是存放在内存中的,主要是防止在容器中导致过度的垃圾实例对象 |
request | 在一次Http请求中,容器会返回该Bean的同一个实例,对不同的Http请求返回不同的bean对象,并且只在该请求中有效 |
session | 在一次的http Session中会产生该bean实例,并且只在当前的httpsession中有效 |
globalSession | 在一个全局的HTTP Session中有用。仅在使用portlet上下文时有效 |
application | 为每个ServletContext创建一个实例对象,仅限在web中使用 |
websocket | 为每个websocket创建一个实例。 |
2、常用作用域——singleton
【特点】:
- 是Spring容器的默认作用域。
- 被singleton修饰的实例,无论引用多少次,在容器中只有一个实例对象。
- 适用于无会话状态的Bean如:(DAO组件,Service组件)
【使用演示】:
- 配置bean(建议不书写作用域,默认就是单例的)
<bean id="cat" class="cn.simplelife.domain.Cat" scope="singleton"/>
- 获取bean
package cn.simplelife.domain;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @ClassName CatTest
* @Description
* @Author simplelife
* @Date 2022/11/18 9:55
* @Version 1.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:cat.xml")
public class CatTest {
@Autowired
private Cat cat;
@Autowired
private Cat cat1;
@Test
public void getCat() {
System.out.println(cat);
System.out.println(cat1);
}
}
- 运行截图
3、常用作用域——prototype
【特点】:
- 对于每个请求该bean的请求都会创建一个新的bean对象
- 存放位置并不是在Spring容器中,而是在内存中。主要是防止容器中的垃圾对象增多。
【使用演示】:
- 配置bean
<bean id="cat" class="cn.simplelife.domain.Cat" scope="prototype"/>
- 获取bean
package cn.simplelife.domain;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @ClassName CatTest
* @Description
* @Author simplelife
* @Date 2022/11/18 9:55
* @Version 1.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:cat.xml")
public class CatTest {
@Autowired
private Cat cat;
@Autowired
private Cat cat1;
@Test
public void getCat() {
System.out.println(cat);
System.out.println(cat1);
}
}
- 运行截图
4、Spring中Bean的生命周期
Sping容器可以管理singleton的作用域的Bean的生命周期,在此作用域下,Spring能够精确的知道该Bean是何时创建的,何时初始化、何时销毁。
对于prototype的Bean实例,Spring只负责创建,并不会跟踪其生命周期。
1、图示Spring中Bean的生命周期
2、过程叙述
- 根据配置情况调用Bean的构造方法或工厂方法实例化Bean。
- 利用依赖注入完成Bean构造方法或工厂方法实例化Bean。
- 如果Bean实现了BeanNameAware接口,则Spring调用Bean的setBeanName(String var1)方法传入当前Bean的id值。
- 如果Bean实现了BeanFactoryAware接口,则Spring调用setBeanFactory(BeanFactory var1)方法,传入当前实例的引用。
- 如果Bean实现了ApplicationContextAware接口,则Spring调用setApplicationContext(ApplicationContext var1)方法,传入当前ApplicationContext实例的引用。
- 如果BeanPostProcessor和Bean关联,则Sping会调用postProcessBeforeInitialization()方法对Bean进行加工操作,SpringAOP就是利用它实现的。
- 如果Bean实现了InitializingBean接口,则Spring调用afterPropertiesSet()方法。
- 如果配置文件中配置了初始化方法,调用该初始化方法。
- . 如果BeanPostProcessor和Bean关联,则Sping会调用postProcessAfterInitialization()方法。
- 如果该bean是单例的就将bean存放在Spring的缓存池中,如果是多例的就交给调用者。
- 如果Bean实现了DisposableBean接口,则Spring会调用destroy()方法将Spring中的bean销毁。如果配置文件提供了销毁方法,调用配置文件中的销毁方法。
5、Bean的装配方式
1、基于XML的装配
Sping在实例化Bean的过程中,Spring首先会调用Bean的默认构造方法来实例化Bean对象,然后通过反射的方式调用Setter方法注入属性值。
因此这种方式注入必须满足两个条件:
1、提供一个无参的构造器。
2、提供setter方法。
- 代码演示
【书写一个User类】
package cn.simplelife.domain;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import java.util.List;
/**
* @ClassName User
* @Description
* @Author simplelife
* @Date 2022/11/21 20:52
* @Version 1.0
*/
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
private String username;
private Integer password;
private List<String> list;
}
【书写配置文件】:
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
<!--使用构造器注入-->
<bean id="user" class="cn.simplelife.domain.User">
<constructor-arg index="0" value="tom"/>
<constructor-arg index="1" value="123"/>
<constructor-arg index="2">
<list>
<value>eat</value>
<value>sleep</value>
<value>play</value>
</list>
</constructor-arg>
</bean>
<!--使用设置注入-->
<bean id="user2" class="cn.simplelife.domain.User">
<property name="username" value="杰瑞"/>
<property name="password" value="123456"/>
<property name="list">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
</bean>
</beans>
【书写测试类】:
package cn.simplelife.domain;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import static org.junit.Assert.*;
/**
* @ClassName UserTest
* @Description
* @Author simplelife
* @Date 2022/11/21 20:59
* @Version 1.0
*/
public class UserTest {
@Test
public void getUserBean() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:user.xml");
User user = applicationContext.getBean("user", User.class);
System.out.println("user = " + user);
User user2 = applicationContext.getBean("user2", User.class);
System.out.println("user2 = " + user2);
}
}
【运行结果】:
2、基于Annotation的装配
-
@Component该注解是一个泛化的概念,仅仅表示一个组件对象(Bean),可以作用在任何层次上。
-
@Repository该注解用于将数据访问层(Dao层)的类标识为Bean,即注解数据访问层Bean,其功能@Componet相同
-
@Service该注解用于标注一个业务逻辑组件类(Service层),其功能与@Component相同
-
@Controller该注解用于标注一个控制器组件类(SpringMVC的Controller),其功能与@Componet相同
-
@Autowired该注解可以对类成员变量、方法及构造方法进行标注,完成自动装配的功能。通过使用@Autowired来消除setter和getter方法。默认按照Bean的类型进行装配。
-
@Resource该注解与@Autowired的功能一样,区别在于该注解默认是按照名称来装配的,只有当找不到与名称匹配的Bean时才会按照类型来装配注入;而@Autowired默认按照Bean的类型进行装配,如果想按照名称来装配注入,则需要和@Qualifier注解一起使用。
@Resource注解有两个属性—name和type。name属性指定Bean实例名称,即按照名称来装配注入;type属性指定Bean类型,即按照Bean的类型进行装配。 -
@Qualifier该注解与@Autowired注解配合使用。当@Autowired注解需要按照名称来装配注入时,需要和该注解一起使用,Bean的实例名称由@Qualifier注解的参数指定。