Spring中的Bean
(一)Bean的配置
Spring可以看做一个大工厂,工厂的作用就是生产和管理Spring容器中的Bean。如果想要使用,就要在Spring配置文件中进行位置。
Spring支持XML和Properties两种格式的配置文件。XML文件中的根元素是< beans>,< beans>包含了多个 < bean>子元素
注意:如果在bean中没有指定id和name,那么Spring会将class值当做id使用。
(二)Bean的实例化
要想使用Spring容器中的Bean,需要实例化Bean。实例化有三种方式:
- 构造器实例化(最常用)
- 静态工厂方式实例化
- 实例工厂方式实例化
(1)构造器实例化
Spring 容器通过 Bean 对应类中默认的无参构造方法来实例化 Bean
(2)静态工厂方式实例化
该方式要求开发者创建一个静态工厂的方法来
创建 Bean 的实例,其 Bean 配置中的 class 属性所指定的不再是 Bean 实例的实现类,而是静
态工厂类,同时还需要使用 factory-method 属性来指定所创建的静态工厂方法 。
(3)实例工厂方式实例化
采用直接创建 Bean 实例的方式 。 同时,在配置文件中,需要实例化的 Bean
也不是通过 class 属性直接指向的实例化类,而是通过 factory- bean 属性指向配置的实例工厂,
然后使用 factory- method 属性确定使用工厂中的哪个方法
(三) Bean的作用域
(1)作用域的种类
(2)singleton作用域
singleton 是 Spring 容器默认的作用域,当 Bean 的作用域为 singleton 时, Spring 容器就
只会存在一个共享的 Bean 实例,并且所有对 Bean 的请求,只要 id 与该 Bean 的 id 属性相匹配,
就会返回同一个 Bean 实例 。
在 Spring 配置文件中, Bean 的作用域是通过元素的 scope 属性来指定的:< bean id="scope " class= "com.iztheima.scope.Scope " scope= " singleton " >
(3)propotype作用域
在使用 prototype 作用域时, Spring 容器会为每个对该 Bean 的请求都创建一个新的实例 。
(四)Bean的生命周期
( 1 )根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean。
(2 )利用依赖注入完成 Bean 中所有属性值的配置注入 。
(3 )如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName()方
法传入当前 Bean 的 id 值。
(4 )如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory()方法传入当前工厂实例的引用 。
(5 )如果 Bean 实现了 ApplicationContextAware 接口,则Spring 调用 setA pplicationContext()方法传入当前 ApplicationContext 实例的引用 。
(6 )如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的预初始化方法postProcessBeforelnitialzation()对 Bean 进行加工操作,这个非常重要, Spring 的 AOP 就是用它实现的 。
(7 )如果 Bean 另见了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet()方法 。
(8 )如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。
(9 )如果有 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化方法 postProcessAfterlnitialization() 。 此时, Bean 已经可以被应用系统使用了 。
( 10 )如果在 中指定了该 Bean 的作用范围为 scope=“singleton” ,则将该 Bean 放入 Spring loC 的缓存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在 中指定了该 Bean 的作用范围为 scope=“prototype” ,贝IJ将该 Bean 交给调用者,调用者管理该 Bean 的生命周期, Spring 不再管理该 Bean 。
( 11 )如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory()方法将 Spring中的 Bean 销毁;如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则Spring 将调用该方法进行销毁 。
(五)Bean的装配方式
Bean的装配可以理解为依赖关系注入(如何使用Bean)。有三种方式:基于XML的装配,基于注解的装配(最常用),自动装配。
(1) 基于XML的装配
Spring 提供了两种基于 XML 的装配方式:设值注入( Setter Injection )和构造注入(Constructor Injection )。
在 Spring 实例化 Bean 的过程中, Spring 首先会调用 Bean 的默认构造方法来实例化 Bean对象,然后通过反射的方式调用 setter 方法来注入属性值。 所以设值注入的Bean需要满足两个要求:
(1)Bean类必须有无参的构造方法
(2)Bean类必须有为注入属性的setter方法
如何设值注入和构造注入:
public class User {
private String username;
private Integer password;
private List<String> list;
/**
* 1.使用构造注入
* 1.1 提供带所有参数的有参构造方法。
*/
public User(String username, Integer password, List<String> list) {
super();
this.username = username;
this.password = password;
this.list = list;
}
/**
* 2.使用设值注入
* 2.1 提供默认空参构造方法;
* 2.2 为所有属性提供 setter方法。
*/
public User() {
super();
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(Integer password) {
this.password = password;
}
public void setList(List<String> list) {
this.list = list;
}
@Override
public String toString() {
return "User [username=" + username + ", password=" + password + ", list=" + list + "]";
}
}
配置文件进行配置
<!-- 设值注入 -->
<bean id="user1" class="com.allen.bean.User">
<property name="username" value="小明" />
<property name="password" value="234234" />
<property name="list">
<list>
<value>111</value>
<value>222</value>
</list>
</property>
</bean>
<!-- 构造注入 -->
<bean id="user2" class="com.allen.bean.User">
<constructor-arg index="0" value="小红" />
<constructor-arg index="1" value="53634" />
<constructor-arg index="2">
<list>
<value>5555</value>
<value>6666</value>
</list>
</constructor-arg>
</bean>
(2)基于注解的装配
Spring 中定义了一系列的注解,常用的注解如下所示 。
• @Component: 可以使用此注解描述 Spring 中的 Bean ,但它是一个泛化的概念,仅仅表
示一个组件 (Bean),并且可以作用在任何层次 。 使用时只需将该注解标注在相应类上即可。
• @Repository: 用于将数据访问层( DAO 层)的类标识为 Spring 中的 Bean ,其功能与@Component 相同
• @Service: 通常作用在业务层( Service 层),用于将业务层的类标识为 Spring 中的 Bean ,
其功能与@Component 相同 。
• @Controller: 通常作用在控制层(如 Spring MVC 的 Controller) ,用于将控制层的类标识
为 Spring 中的 Bean ,其功能与 @Component 相同 。
• @Autowired: 用于对 Bean 的属性变量、属性的 setter 方法及构造方法进行标注,配合对
应的注解处理器完成 Bean 的自动配置工作。 默认按照 Bean 的类型进行装配。
• @Resource: 其作用与 Autowired 一样。 其区别在于@Autowired 默认按照 Bean 类型装
配,而@Resource 默认按照 Bean 实例名称进行装配。 @Resource 中有两个重要属性: name
和 type o Spring 将 name 属性解析为 Bean 实例名称, type 属性解析为 Bean 实例类型 。 如果
指定 name 属性,贝IJ按实例名称进行装配;如果指定 type 属性,则按 Bean 类型进行装配;如
果都不指定,则先按 Bean 实例名称装配,如果不能匹配,再按照 Bean 类型进行装自己;如果都
无法匹配,则抛出 NoSuchBeanDefinitionException 异常 。
• @Qualifier: 与@Autowired 注解配合使用,会将默认的按 Bean 类型装配修改为接 Bean
的实例名称装配, Bean 的实例名称由 @Qualifier 注解的参数指定 。
在上面几个注解中,虽然@Repository 、 @Service 与@Controller 功能与@Component 注解
的功能相同,但为了使标注类本身用途更加清晰,建议在实际开发中使用 @Repository 、 @Service
与@Controller 分别对实现类进行标注。
@Repository
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("UserDao保存");
}
}
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public void add() {
userDao.save();
System.out.println("service层保存");
}
}
<?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-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 注解 -->
<context:annotation-config />
<!-- 扫描包, 减少bean的创建-->
<context:component-scan base-package="com.allen.annotation"/>
</beans>
public class MyTest {
@Test
public void MyTestBean() {
ApplicationContext app = new ClassPathXmlApplicationContext("com/allen/annotation/Bean2.xml");
UserService bean = (UserService) app.getBean("userService");
bean.add();
}
}
注:当用扫描包时,需在最顶层类的注解中添加命名,否则获取不到Bean。在service层,如果使用@Resource注解,同样加入命名。
(3)自动装配
增加了 autowire 属性,并将其属性值设置为 by队lame
<?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-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<bean id="userDao" class="com.allen.annotation.dao.UserDaoImpl" />
<bean id="userService" class="com.allen.annotation.service.UserServiceImpl"
autowire="byName" />
</beans>
在文件中增加类属性的 setter 方法,引入Dao
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void add() {
userDao.save();
System.out.println("service层保存");
}
}