铁锤的IT奇妙探险 Java Back-End Coder

Spring的Bean对象和DI

2020-07-03


本文核心关注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);
	}
}

作用域

  1. singleton:表示在 Spring 容器中只有一个 Bean 实例,以单例的形式存在,是默认的 Bean 作用域。
  2. prototype:原型作用域,每次调用 Bean 时都会创建一个新实例,也就是说每次调用 getBean() 方法时,相当于执行了 new Bean()。
  3. request:每次 Http 请求时都会创建一个新的 Bean,该作用域仅适应于 WebApplicationContext 环境。
  4. session:同一个 Http Session 共享一个 Bean 对象,不同的 Session 拥有不同的 Bean 对象,仅适用于 WebApplicationContext 环境。
  5. 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标签中通过nameref属性进行说明,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"/>

Similar Posts

Comments