本文核心关注bean对象的注册,生命周期以及Spring依赖注入的三种方式。
Spring及Ioc
Bean对象
- 同名 Bean 指的是多个 Bean 有相同的 name 或者 id。Spring 对待同名 Bean 的处理规则是使用最后面的 Bean 覆盖前面的 Bean,所以我们在定义 Bean 时,尽量使用长命名非重复的方式来定义,避免产生同名 Bean 的问题。Bean 的 id 或 name 属性并非必须指定,如果留空的话,容器会为 Bean 自动生成一个唯一的名称,这样也不会出现同名 Bean 的问题。
注册方式
XML配置文件注册方式
<bean id="person" class="org.springframework.beans.Person">
<property name="id" value="1"/>
<property name="name" value="Java"/>
</bean>
Java注解注册方式
@Component
public class Person {
private Integer id;
private String name
// 忽略其他方法
}
@Configuration
public class Person {
@Bean
public Person person(){
return new Person();
}
// 忽略其他方法
}
API注册方式
public class CustomBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
RootBeanDefinition personBean = new RootBeanDefinition(Person.class);
// 新增 Bean
registry.registerBeanDefinition("person", personBean);
}
}
作用域
- singleton:表示在 Spring 容器中只有一个 Bean 实例,以单例的形式存在,是默认的 Bean 作用域。
- prototype:原型作用域,每次调用 Bean 时都会创建一个新实例,也就是说每次调用 getBean() 方法时,相当于执行了 new Bean()。
- request:每次 Http 请求时都会创建一个新的 Bean,该作用域仅适应于 WebApplicationContext 环境。
- session:同一个 Http Session 共享一个 Bean 对象,不同的 Session 拥有不同的 Bean 对象,仅适用于 WebApplicationContext 环境。
- application:全局的 Web 作用域,类似于 Servlet 中的 Application。
生命周期
依赖注入
构造方法注入
public class UserService implements IUserService {
private IUserDao userDao;
private User user;
public UserService(IUserDao userDao, User user) {
this.userDao = userDao;
this.user = user;
}
public void loginUser() {
userDao.loginUser();
}
}
<!-- 注册userService -->
<bean id="userService" class="com.lyu.spring.service.implUserService">
<constructor-arg name="userDao" ref="userDaoJdbc"><constructor-arg>
<constructor-arg name="user" ref="user"></constructor-arg>
</bean>
<!-- 注册实体User类,用于测试 -->
<bean id="user" class="com.lyu.spring.entity.User"></bean>
<!-- 注册jdbc实现的dao -->
<bean id="userDaoJdbc" class="com.lyu.spring.dao.implUserDaoJdbc"></bean>
- 当构造方法有多个参数时,则需要注入的参数都需要在xml文件中注册,且在constructor-arg标签中通过name和ref属性进行说明,
name
为参数列表中的参数名,ref
是该参数实体类配置的id。
setter注入
<!-- 注册userService -->
<bean id="userService" class="com.lyu.spring.service.impl.UserService">
<!-- 写法一 -->
<!-- <property name="UserDao" ref="userDaoMyBatis"></property> -->
<!-- 写法二 -->
<property name="userDao" ref="userDaoMyBatis"></property>
</bean>
<!-- 注册mybatis实现的dao -->
<bean id="userDaoMyBatis" class="com.lyu.spring.dao.impl.UserDaoMyBatis"></bean>
name属性值与类中的成员变量名以及set方法的参数名都无关,只与对应的set方法名有关
基于注解注入
- 有四种注解可以
注册bean
,Component,Repository,Controller,Service。注意这四个注解只是负责bean对象的创建
(注册),用来修饰类,标记这些类要生成bean; - 用于注入的注解只有两个:
@Autowired
和@Resource
,用来修饰字段,构造函数或设置方法; @Autowired
是通过byType
形式,用来给指定的字段或方法注入所需的外部资源;- default-autowire,它是在xml文件中进行配置的,可以设置为byName、byType、constructor和autodetect;
- constructor:通过
构造方法
进行自动注入,spring会匹配与构造方法参数类型一致的bean进行注入 - byName:被注入
bean的id
名必须与set方法后半截匹配,并且id名称的第一个单词首字母必须小写,这一点与手动set注入有点不同; - byType:查找所有的
set
方法,将符合参数类型的bean注入; - 除了在某个
bean配置文件
的<beans/>
标签中使用default-autowire
属性,还可以针对单独一个bean
配置autowire
属性,如果没有设置,则默认采用父标签的default-autowire
的值; - Resource:java的注解,默认以byName的方式去匹配与属性名相同的bean的id,如果没有找到就会以byType的方式查找,如果byType查找到多个的话,使用
@Qualifier
注解(spring注解)指定某个具体名称的bean。
default-autowire的使用
<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"
default-autowire="byName">
autowire的用法:
<bean id="auto" class="example.autoBean" autowire="byType"/>