什么是Spring中的Bean???
Bean实际上是一个普通的java类,普通java类配置到spring的配置文件中,通过容器来生成对象,生成出来的对象就叫做Bean。如果把Sping看做一个大型工厂,则Spring容器中的Bean就是该工厂的产品。要想使用这个工厂生产或管理Bean,就需要在配置文件中告诉他需要哪些Bean,以及需要使用何种方式将这些Bean装配到一起。
Bean的配置
Spring中的XML配置文件的根元素是< beans >,< beans >中包含 了多个< bean>子元素,每一个< bean >子元素定义了一个Bean,并捲述了该Bean如何被装配到Spring容器中。关于< beans >元素的常用属性如下表所示:
Bean的实例化
Bean的实例化有哪些方式?
在面向对象的程序中,要想使用某个对象,就需要先实例化这个对象。同样,在Spring中,要想使用容器中的Bean,也需要实例化Bean。实例化Bean有三种方式:构造器实例化,静态工厂方式实例化和实例化工厂方式实例化(其中最常用的是构造器实例化)
构造器实例化
构造器实例化是指Spring容器通过Bean(普通java类)对应的类中默认的构造函数(无参构造函数)来实例化Bean。接下来演示一下构造器实例化:
1、创建一个普通java类
//使用类中默认的无参构造方法
public class Bean1 {}
2、编写配置文件
//id为唯一标识符,class表示的是bean的全限定名,表明bean所在的位置
<bean id="bean1" class="com.mq.contructor.Bean1"></bean>
3、测试
在main方法中执行,若能打印出实例化bean的地址,则成功实例化bean
//定义配置文件路径
String xmlPath="com/mq/contructor/Bean1.xml";
//ApplicationContext 在加载配置文件时,对Bean进行实例化
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath);
Bean1 bean=(Bean1)applicationContext.getBean("bean1");
System.out.println(bean);
静态工厂实例化
静态工厂是实例化Bean的另一种方法。该方法要求自己创建一个静态工厂的方法来创建Bean的实例。
1、创建一个普通java类
public class Bean2 {}
2、创建一个工厂,并且一定要有一个静态的方法
public class MyBean2Factory {
public static Bean2 createBean() {
return new Bean2();
}
}
3、编写spring配置文件(class写静态工厂的全限定名)
//factory-method的值为具体的方法名称
<bean id="bean2" class="com.mq.factory.MyBean2Factory"
factory-method="createBean"></bean>
4、编写测试类
同样能成功打印出实例化bean的地址
//定义配置文件的路径
//ApplicationContext在加载配置文件,对Bean进行实例化
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("com/mq/factory/Bean1.xml");
System.out.println(applicationContext.getBean("bean2"));
实例工厂方法实例化
实例工厂是采用直接创建Bean实例的方式,在配置文件中,通过factory-bean属性来配置一个实例工厂,然后通过factory-method属性确定使用工厂中的哪个方法。
1、创建普通java类
2、创建一个工厂,并且为无参构造函数加入一条打印语句,输出则证明MyBean3Factory被实例化
public class MybBean3Factory {
public MybBean3Factory() {
System.out.println("Bean3工厂实例化!");
}
public Bean3 createBean() {
return new Bean3();
}
}
3、编写测试类
//指定配置文件路径
String xmlPath="com/mq/factory1/Bean3.xml";
//ApplicationContext加载配置文件时,对Bean进行实例化
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath);
System.out.println(applicationContext.getBean("bean3"));
Bean3对象被成功实例化,并且打印出无参构造方法中的的输出语句。
Bean的作用域
在Spring中,bean作用域用于确定哪种类型的bean实例应该从Spring容器中返回给调用者。Spring中为Bean的实例定义了7种作用域,如下所示
1、singleton作用域
Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。 singleton是Spring容器默认的作用域,当Bean的作用域为singleton时,Spring容器就只会在一个共享的Bean实例。singleton作用域对于无会话状态的Bean(Dao组件,Service组件)来说是最理想的选择。
在配置文件中,配置scope属性为singleton
<bean id="scope" class="com.mq.scope.Scope" scope="singleton"></bean>
在测试类中进行测试:
// 定义配置文件路径
String classPath = "com/mq/scope/Bean4.xml";
// 加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(classPath);
// 输出获得的实例
System.out.println(applicationContext.getBean("scope"));
System.out.println(applicationContext.getBean("scope"));
System.out.println(applicationContext.getBean("scope"));
System.out.println(applicationContext.getBean("scope"));
接下来通过getBean()方法获取多个实例对象,都只获取同一个实例对象,运行结果如下:
prototype作用域
prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。 在需要保持会话状态的Bean(如Struts2的Action类)应该使用prototype作用域。在使用prototype作用域是,Spring容器回为每个对该Bean的请求都创建一个新的实例。 修改配置文件的scope属性为prototype:
<bean id="scope" class="com.mq.scope.Scope" scope="prototype"></bean>
再运行测试类,结果如下:
Bean的生命周期
了解Spring中Bean的生命周期的意义就在于,可以利用Bean在其 存活期间的特定时刻完成一些相关操作。这种时刻可能有很多,但一 般情况下,常会在Bean的postinitiation(初始化后)和predestruction(销 毁前)执行一些相关操作。例如初始化后要传一些初始化参数,销毁前要关闭一些找资源
Spring容器中Bean的生命周期流程如下图所示:
为了更好的演示Bean的生命周期,通过一个小案例来进行演示: 1、在普通java类中自定义构造方法、初始化方法和销毁方法
public class life {
//构造方法,也是实例化
public life() {
System.out.println("life START!!");
}
//初始化方法
public void initMethod() {
System.out.println("initMethod START!!!");
}
//销毁方法
public void destroyMethod() {
System.out.println("destroyMethod START!!!!");
}
}
2、在配置文件中做如下配置,配置自定义的初始化方法和销毁方法:
<!-- scope="singleton" 默认为ingleton作用域,这种情况下spring能够全程跟踪bean的生命周期 -->
<bean id="life" class="com.mq.life.life" init-method="initMethod" destroy-method="destroyMethod"></bean>
3、编写测试类进行测试
//定义配置文件路径
String xmlPath="com/mq/life/life.xml";
//classPathXmlApplication 在加载配置文件时,对Bean进行实例化
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext(xmlPath);
//ClassPathXmlApplicationContext 提供了关闭容器的方法,这样Bean的销毁方法才会被调用
context.close();
运行结果如下:
可见分别调用了自定义的构造方法,初始化方法和销毁方法。
什么时Bean的装配??
Bean的装配可以理解为依赖关系注入,Bean的装配方式即Bean依赖注入的方式。spring容器支持多种形式的Bean的装配方式,如基于XML的装配、基于注解(Annotation)的装配和自动装配(其中最常用的是基于注解的装配)。
基于Annotation的装配(注解)
基于XML的装配可能会导致XML配置文件过于臃肿,给后续的维护和升级带来一定困难。为此,Sping还提供了基于Annotation(注解)技术的全面支持,常见的注解如下:
| 项目 | 价格 |
|---|---|
| @Component | 用于描述Spring中的Bean,他是一个泛化的概念 |
| @Repository | 用于将数据访问层(DAO)的类标识为Spring中的Bean |
| @Service | 用于业务层(Service)的类标识为Spring中的Bean |
| @Autowired | 用于对Bean的属性变量、属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作 |
| @Resource | 其作用与Autowired一样。@Resource中有两个重要属性:name和type。Sping将name属性解析为Bean实例名称,type属性解析为Bean实例类型 |
| @Qualifier | 与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean的实例名称装配,Bean的实例名称有@Qualifier注解的参数指定 |
接下来通过一个实例来演示:
1、创建UserDao和UserService接口
public interface UserDao {
public void save();
}
public interface UserService {
public void save();
}
2、创建接口实现类并加入注解
@Repository("userDao")
public class UserDaoImpl implements UserDao{
@Override
public void save() {
System.out.println("userDao---save---");
}
}
3、编写service层并加入Service注解
@Service("userService")
public class UserServiceImpl implements UserService {
@Resource(name="userDao")
private UserDao userDao;
@Override
public void save() {
//调用userDao中的save方法
this.userDao.save();
System.out.println("userService----save---");
}
}
通过注解@Resource注入UseDao实例
3、创建controller类
@Controller("userController")
public class UserController {
@Resource(name="userService")
private UserService userService;
public void save() {
this.userService.save();
System.out.println("userController----save-----");
}
}
4、编写Bean.xml配置文件
<!-- 使用context命名空间,在配置文件中开启响应的注解处理器
<context:annotation-config></context:annotation-config>
<!-- 分别定义三个bean实例 -->
<bean id="userDao" class="com.mq.annotation.UserDaoImpl"></bean>
<bean id="userService" class="com.mq.annotation.UserServiceImpl"></bean>
<bean id="userController" class="com.mq.annotation.UserController"></bean>
5、编写测试类
public class test {
public static void main(String[] args) {
// 定义配置文件的路径
String xmlPath = "com/mq/annotation/Bean6.xml";
// 加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
// 获取UserController实例
UserController controller = (UserController) applicationContext.getBean("userController");
// 调用UserController中的save()方法
controller.save();
}
}
方法二:同过包扫描,将这些组件纳入spring容器进行管理,在xml配置文件中进行如下配置:
<!-- 使用context命名空间,通知spring扫描指定包所有的bean类进行注解解析 -->
<context:component-scan base-package="com.mq.annotation"></context:component-scan>
不在需要一个一个bean进行配置
5、自动装配
所谓自动装配,就是将一个Bean自动的注入到到其他Bean的Property中。Spring的元素中包含一个autowire属性,我们可以通过设置autowire的属性值来自动装配Bean。autowlre属性有5个值,其值及说明下表所示: