1.Bean的配置
Spring可以看做是一个大型工厂,这个工厂的作用就是生产和管理Bean,如果想要在这个项目中使用这个工厂,就需要开发者对spring的配置文件进行配置
Spring支持XML和Properties两种格式的配置文件,在实际中最常用的是XML,XML配置文件的根元素是<beans>,当中包含了多个<bean>子元素,描述了bean如何被装配到Spring容器中.
<bean>元素的常用属性及其子元素
属性或子元素名称
| 描述 |
---|---|
id | 是一个Bean的唯一标识符,类似于身份证 |
name | 为Bean指定名称,多个用逗号隔开 |
class | 指定了Bean的具体实现类,必须是实现类的完整的全限定类名 |
scope | 设定Bean的作用域:属性值有singleton(单例)prototype(多例)request,session,global Session,application,websocket |
constructor-arg | <bean>元素的子元素,可以使用此元素传入构造参数实例化.该元素的index属性值指定构造参数的序号(从0开始),type属性指定构造参数的类型,参数值可以通过ref属性或value属性直接指定,也可以通过ref或value子元素指定 |
property | <bean>元素的子元素,用于调用Bean实例中的setter方法完成属性赋值,从而完成依赖注入,该元素的name属性指定Bean实例中的相应属性名,ref属性或value属性用于指定参数值 |
ref | <property><constructor-arg>等元素的属性或子元素,可以用于指定对Bean工厂中某个Bean实例的引用 |
value | <property><constructor-arg>等元素的属性或子元素,可以用于直接指定一个常量值 |
list | 用于封装List或数组类型的依赖注入 |
set | 用于封装set类型属性的依赖注入 |
map | 用于封装map类型属性的依赖注入 |
entry | <map>元素的子元素,用于设置一个键值对,其key属性指定字符串类型的键值,ref或value子元素指定其值,也可以通过value-ref或value属性指定其值 |
示例代码如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 存放项目需要 实例的 javabean对象 -->
<beans>
<!--
bean 就是用来配置 类的路径
配置 每个对象的信息
id 标识符
class 实例化对象的全限定类名
-->
<bean id="accountService" class="com.itheima.service.AccountServiceImpl"></bean>
<bean id="accountDao" class="com.itheima.dao.AccountDaoImpl"></bean>
</beans>
注意:如果bean中未指定id和name,则spring会将class值当成id使用.
2.Bean的实例化
实例化bean有三种方式:构造器实例化,静态工厂实例化和实例工厂方式实例化
2.1构造器实例化是指通过Bean对应类中默认的无参构造方法来实例化Bean
(1)导入依赖的jar包
(2)创建Bean1类
(3)创建配置文件beans1.xml
<bean id="bean1" class="com.itcast.Bean1">
(4)创建测试类Test1
public class Test1{
public static void main (String []args){
//1.定义配置文件路径
String xml path="com/itcast/beans1.xml";
//ApplicationContext 在加载配置文件时,对Bean进行实例化
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlpath);
Bean1 bean =(Bean1) applicationContext.getBean("bean1");
System.out.println(bean);
}
}
2.2静态工厂方式实例化
该方式要求开发者创建一个静态工厂的方法来创建Bean的实例,其Bean中的class属性指定的是静态工厂类,同时还需要使用factory-method属性来指定所创建的静态工厂方法
(1)创建一个Bean2类
(2)创建一个MyBean2Factory类,并在类中创建一个静态方法
public class MyBean2Factory{
//使用自己的工厂创建Bean2实例
public static Bean2 createBean(){
return new Bean2();
}
}
(3)创建配置文件beans2.xml
<bean id="bean2"
class="com.itcast.MyBean2Factory"
factory-method="createBean"/>
(4)测试类Test2
public class Test2{
public static void main (String []args){
//1.定义配置文件路径
String xml path="com/itcast/beans2.xml";
//ApplicationContext 在加载配置文件时,对Bean进行实例化
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlpath);
System.out.println(applicationContext.getBean("bean2"));
}
}
2.3实例工厂方式实例化
该方法采用直接创建Bean实例的方式,同时,在配置文件中,需要实例化的Bean通过factory-bean属性指向配置的实例工厂,然后使用
factory-method属性确定使用工厂中的哪个方法
(1)创建Bean3类
(2)创建工厂类MyBeans3Factory
public class Bean3{
public MyBean3Factory(){
System.out.println("bean3工厂实例化中")
}
//创建Bean3实例的方法
public Bean3 createBean(){
return new Bean3();
}
}
(3)创建beans3.xml
<bean id="MyBeans3Factory"
class="com.itcast.MyBeans3Factory"
使用factory-bean属性指向配置的实例工厂
使用factory-method属性确定使用工厂中的哪个方法
<bean id="bean3" factory-bean="MyBeans3Factory"
factory-method="createBean"/>
(4)测试类Test3
public class Test3{
public static void main (String []args){
//1.定义配置文件路径
String xml path="com/itcast/beans3.xml";
//ApplicationContext 在加载配置文件时,对Bean进行实例化
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlpath);
System.out.println(applicationContext.getBean("bean3"));
}
}
3.Bean的作用域
3.1作用域的种类
作用域名称 | 说明 |
---|---|
singleton(单例) | 无论多少个bean引用它,始终指向同一个对象 |
prototype(原型) | 每次通过Spring容器获取的prototype定义的Bean时,容器都将创建一个新的Bean实例
|
request | 在一次HTTP请求中,容器会返回该Bean的同一个实例,对不同的HTTP请求则会产生一个新的Bean,而且该Bean仅在当前HTTPRequest内有效 |
session | 在一次HTTPSession中,容器会返回该Bean的同一个实例.对不同的HTTP请求则会产生一个新的Bean,而且该Bean仅在当前HTTPSession内有效 |
globalSession | 在一个全局的HTTPSession中,容器会返回该Bean的同一个实例.仅在使用portlet上下文时有效 |
application | 为每个ServletContext对象创建一个实例.仅在web相关的ApplicationContext中有效 |
websocket | 为每个websocket对象创建一个实例,仅在web相关的ApplicationContext中有效 |
4.Bean的生命周期
生命周期执行描述如下:
(1)根据配置情况调用Bean构造方法或工厂方法实例化Bean
(2)利用依赖注入完成Bean中所有属性值的配置注入
(3)如果Bean实现了BeanNameAware接口,则Spring调用Bean的setBeanName()方法传入当前Bean的id值
(4)如果Bean实现了BeanFactoryAware接口,则Spring调用setBeanFactory()方法传入当前工厂实例的引用
(5)如果Bean实现了ApplicationContextAware接口,则spring调用setApplicationContext方法传入当前ApplicationContext实例的引用
(6)如果BeanPostProcessor和Bean关联,则spring将调用该接口的欲初始化方法postProcessBeforeInitialization()对Bean进行加工操作,这个非常重要,spring的AOP就是用它实现的
(7)如果Bean实现了InitializingBean接口,则Spring将调用afterPropertiesSet()方法
(8)如果在配置文件中通过init-method属性指定了初始化方法,则调用该初始化方法
(9)如果有BeanPostProcessor和Bean关联,则Spring将调用该接口的初始化方法postProcessAfterInitialization(),此时Bean已经可以被应用系统使用了
(10)如果在<bean>中指定了该Bean的作用范围为scope"singleton",则将该Bean放入SpringIOC的缓存池中,将触发Spring对该Bean的生命周期管理,如果指定范围为scope"prototype",则将该Bean交给调用者,调用者管理该Bean的生命周期,Spring不再管理该Bean
(11)如果Bean实现了DisposableBean接口,则spring会调用destory()方法将Spring中的Bean销毁,如果在配置文件中通过destory-method属性指定了Bean的销毁方法,则Spring将调用该方法进行销毁.
5.Bean的装配方式
5.1基于XML的装配
在spring实例化Bean的过程中,spring首先会调用Bean的默认构造方法来实例化Bean对象,然后通过反射的方式调用setter方法来注入属性值,因此注入一个Bean的必须要做到以下两点
- Bean类必须提供一个默认的无参构造方法
- Bean类必须为需要注入的属性提供对应的setter方法
(1)创建一个com.itcast.User类,类中定义username,password,和list及其对应的setter方法
(2)com.itcast.beans5.xml
<!--使用构造注入方式装配User实例-->
<bean id="user1" class="com.itcast.User">
<construcoor-arg index="0" value="tom"/>
<construcoor-arg index="1" value="123456"/>
<construcoor-arg index="2" >
<list>
<value>"constructorvalue1"</value>
<value>"constructorvalue2"</value>
</list>
</constructor-arg>
</bean>
<!--2.使用设置注入方式装配User实例-->
<bean id="user2" class="comitcast.User">
<property name="username" value="张三"></property>
<property name="password" value="123456"></property>
<!--注入list集合-->
<property name="list">
<list>
<value>"setlistvalue1"</value>
<value>"setlistvalue2"</value>
</list>
<property>
</bean>
在上述配置文件中<constructor-arg>元素用于定义构造方法的参数,其属性index表示其索引(从0开始),value属性用于设置注入的值,其子元素<list>来为User类中的list集合属性注入值.然后又使用了设置注入的方式装配User类的实例,其中<property>元素用于调用Bean中的setter方法完成属性赋值,从而完成依赖注入,而其子元素<list>同样也是为User类中对应的list集合属性注入值.
(3)创建测试类Test
public class Test{
public static void main (String[]args){
//定义配置文件路径
String xmlpath="com.itcast.beans5.xml";
//加载配置文件
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlpath);
//构造方式输出结果
System.out.println(applicationContext.getBean("User1"));
System.out.println(applicationContext.getBean("User2"));
}
}
5.2基于Annotation的装配
@Component | 可以使用此注解描述Spring中的Bean,可以作用在任何层次 |
@Repository | 用于将数据访问层(Dao)中的类标识为Spring中的Bean,其功能与@Component相同 |
@Service | 通常作用在业务层Service,用于将业务层的类标识为Spring中的Bean |
@Controller | 通常作用在控制层(如SpringMVC中的Controller),用于将控制层的类标识为Spring中的Bean,其功能与@Component相同 |
@Autowired | 用于对Bean的属性变量,属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作.默认按照Bean的类型进行装配 |
@Resource | 用于对Bean的属性变量,属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作.默认按照Bean的实例名称进行装配@Resource有两个重要的属性,name为Bean的实例名称,type为Bean的实例类型 |
@Qualifier | 与@Autowired注解配合使用,会将默认的按照Bean类型装配修改成按照Bean的实例名称进行装配,Bean的实例名称由@Qualifier注解的参数指定 |
小案例
(1)UserDao
public interface UserDao{
public void save();
}
(2)UserDaoImpl
@Repository("userDao")
public class UserDaoImpl implements UserDao{
public void save(){
System.out.println("userdao...save...");
}
}
(3)UserService
public interface UserService{
public void save();
}
(4)UserServiceImpl
@Service("userService")
public class UserServiceImpl implements UserService{
@Resource(name="userDao")
private UserDao userDao;
public void save(){
//调用UserDao中的save方法
this.userDao.save();
System.out.println("userservice...save...");
}
}
(5)UserController
@Controller("userController")
public class UserController{
@Resource(name="userService")
private UserService userService;
public void save(){
this.userService.save();
System.out.println("userController...save...");
}
}
(6)beans6.xml
<!--使用context命名空间,在配置文件中开启对应的注解处理器-->
<context:annotation-config/>
<!--分别定义3个Bean实例-->
<bean id="userDao" class="com.itcast.userDaoImpl"/>
<bean id="userService" class="com.itcast.userServiceImpl"/>
<bean id="userController" class="com.itcast.userController"/>
对包路径下所有Bean文件进行扫描,其配置方式如下:
<context:component-scan base-package="指定包下的所有Bean类">
(7)测试类Test
public class Test{
//定义配置文件路径
String xmlpath="com.itcast.beans6.xml";
//加载配置文件
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlpath);
//获取UserController实例
UserController userController=(UserController)applicationContext.getBean("userController");
//调用UserController中的save方法
userController.save();
}
}
5.3自动装配
spring中的<bean>元素中包含一个autowire属性,可以通过设置autowire的属性值来自动装配Bean,所谓的自动装配就是将一个Bean自动得注入到其它Bean的property当中
default | 由<bean>的上级标签<beans>的default-autowire属性值确定.例如<beans default-autowire="byName"> |
byName | 根据属性的名称自动装配,容器将根据名称查找与属性完全一致的Bean,并将其属性自动装配 |
byType | 根据属性的数据类型自动装配,如果一个Bean的数据类型,兼容另一个Bean中的数据类型,则自动装配. |
constructor | 根据构造函数的参数类型,进行bytype自动装配 |
no | 在默认情况下,不使用自动装配,Bean依赖必须通过ref元素定义 |
例如:
<bean id="userDao" class="com.itcast.userDaoImpl"/>
<bean id="userService" class="com.itcast.userServiceImpl" autowire="byName"/>
<bean id="userController" class="com.itcast.userController"autowire="byName"/>