SSM之Spring(二)Bean

在 Spring 中,那些组成应用程序的主体及由 Spring IOC 容器所管理的对象,被称之为 bean。简单地讲,bean 就是由 IOC 容器初始化、装配及管理的对象。

创建(装配)bean的方式

创建Bean,也就是在IOC容器中装配Bean,现在主要用的方式是注解方式。而装配Bean用的方式就是依赖注入,用的方式主要是属性注入

在面向对象的程序中,要想调用某个类的成员方法,就需要先实例化该类的对象。根据配置的方式主要分为两大类。

XML方式配置

这种方式主要通过xml文件的配置

setter方式

java代码

public interface IUserDao {
    void addUser();
    void delUser();
    void updateUser();
}
   
public class UserDaoImpl implements IUserDao {
	public void addUser() {
		System.out.println("addUser方法被调用了");
	}  
	public void delUser() {
		System.out.println("delUser方法被调用了");
	}  
	public void updateUser() {
		System.out.println("updateUser方法被调用了");
	}
}
public class UserAction {
	private IUserDao dao; //dao是一个依赖对象,要由springg进行管理,要生成 get set 方法
	public void execute(){
		dao.addUser();
		dao.updateUser();
		dao.delUser();
	}
}

xml配置

//配置文件
<bean name="userAction_name" class="cat.action.UserAction" >
<property name="dao" ref="userDao_name" /> //引用的是下面的名称
</bean> 
<bean name="userDao_name" class="cat.dao.UserDaoImpl" />
//测试
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
UserAction action=(UserAction)ctx.getBean("userAction_name");
action.execute(); 
构造函数

java代码

public class UserAction {
  //public UserAction(){} 可以保保留一个无参的构造函数 
  //这是几个依赖对象,不用生成get set方法了
  private UserInfo user;
  private String school;
  private IUserDao dao;  
  //希望Spring 由构造函数注入依赖对象
public UserAction(IUserDao dao,UserInfo user,String school){
	this.dao=dao;
	this.school=school;
	this.user=user;
} 
public void execute(){
	dao.addUser();
	dao.updateUser();
	dao.delUser(); 
	System.out.println(user);
	System.out.println(school);
}

xml文件配置

//配置文件
<bean name="userInfo_name" class="cat.beans.UserInfo" >
  <property name="id" value="1" />
  <property name="userName" value="周周" />
  <property name="password" value="123" />
  <property name="note" value="这是备注" />
</bean>   
<bean name="userAction_name" class="cat.action.UserAction" >
  <constructor-arg ref="userDao_name" />
  <constructor-arg ref="userInfo_name" />
  <constructor-arg value="哈尔滨师范大学" />
</bean> 
/*
也可以指定 索引和 type 属性,索引和type 都可以不指定
<bean name="userAction_name" class="cat.action.UserAction" >
<constructor-arg index="0" ref="userDao_name" type="cat.dao.IUserDao" /> 如果是接口,就不能指定是实现类的类型
<constructor-arg index="1" ref="userInfo_name" type="cat.beans.UserInfo" />
<constructor-arg index="2" value="哈尔滨师范大学" />
</bean>
*/   
<bean name="userDao_name" class="cat.dao.UserDaoImpl" />
静态工厂方式

java代码

//工厂,用来生成dao的实现类
public class UserDaoFactory {
	public static IUserDao createUserDaoInstance(){
	  return new UserDaoOracleImpl();
	  }
} 
public class UserAction {
	private IUserDao dao;//使用工厂方式注值,也要生成set方法
	public void execute(){
	dao.addUser();
	dao.updateUser();
	dao.delUser();
	}
	public void setDao(IUserDao dao) {
	this.dao = dao;
	} 
}

xml文件配置

//配置文件 
<bean name="userAction_name" class="cat.action.UserAction" >
<property name="dao" ref="userDao_name" />
</bean>
<bean name="userDao_name" class="cat.dao.UserDaoFactory" factory-method="createUserDaoInstance" />
实例工厂

java代码

//工厂 =>
public class UserDaoFactory {
//这个方法不是静态的
public IUserDao createUserDaoInstance(){
  return new UserDaoOracleImpl();
  }
}

xml文件配置

//配置文件 
<bean name="userAction_name" class="cat.action.UserAction" >
<property name="dao" ref="userDao_name" />
</bean>
<bean name="userDaoFactory_name" class="cat.dao.UserDaoFactory" />
<bean name="userDao_name" factory-bean="userDaoFactory_name" factory-method="createUserDaoInstance" />
自动装配

自动装配就是指 Spring 容器可以自动装配(autowire)相互协作的 Bean 之间的关联关系,将一个 Bean 注入其他 Bean 的 Property 中。要使用自动装配,就需要配置 元素的 autowire 属性。autowire 属性有五个值
在这里插入图片描述

注解方式

直接作用在java类上面,例如:@Component、@Repository、@Service、@Controller等等,这些注解的具体作用在后面会讲解到。

Java类配置方式

在标注了@Configuration的java类上,通过在类方法上标注@Bean定义一个bean。方法必须提供Bean的实例化逻辑。

几种方式的对比

在这里插入图片描述
在这里插入图片描述
应用场景
在这里插入图片描述

Bean的作用域

Spring Framework支持五种作用域,五种作用域中,request、session 和 global session 三种作用域仅在基于web的应用中使用(不必关心你所采用的是什么web应用框架),只能用在基于 web 的 Spring ApplicationContext 环境。

singleton

唯一 bean 实例

当一个 bean 的作用域为 singleton,那么Spring IoC容器中只会存在一个共享的 bean 实例,并且所有对 bean 的请求,只要 id 与该 bean 定义相匹配,则只会返回bean的同一实例。
singleton 是单例类型(对应于单例模式),就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,但我们可以指定Bean节点的 lazy-init=”true” 来延迟初始化bean,这时候,只有在第一次获取bean时才会初始化bean,即第一次请求该bean时才初始化。 每次获取到的对象都是同一个对象。注意,singleton 作用域是Spring中的缺省作用域。

要在XML中将 bean 定义成 singleton ,可以这样配置:

<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton"> 

也可以使用注解的方式:@Scope 注解(它可以显示指定bean的作用范围。)的方式

@Service
@Scope("singleton")
public class ServiceImpl{

}

prototype

每次请求都会创建一个新的 bean 实例

当一个bean的作用域为 prototype,表示一个 bean 定义对应多个对象实例。 prototype 作用域的 bean 会导致在每次对该 bean 请求(将其注入到另一个 bean 中,或者以程序的方式调用容器的 getBean() 方法)时都会创建一个新的 bean 实例prototype 是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象根据经验,对有状态的 bean 应该使用 prototype 作用域,而对无状态的 bean 则应该使用 singleton 作用域。

在 XML 中将 bean 定义成 prototype ,可以这样配置:

<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/>  
 或者
<bean id="account" class="com.foo.DefaultAccount" singleton="false"/> 

也可以使用注解的方式配置:

@Service
@Scope("prototype")
public class ServiceImpl{

}

request

每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。

request只适用于Web程序,每一次 HTTP 请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效,当请求结束后,该对象的生命周期即告结束。 在 XML 中将 bean 定义成 request ,可以这样配置:

xml文件配置:

<bean id="loginAction" class=cn.csdn.LoginAction" scope="request"/> 

也可以使用注解的方式配置:

@Service
@Scope("request")
public class ServiceImpl{

}

session

每一次HTTP请求都会产生一个新的 bean,该bean仅在当前 HTTP session 内有效。

session只适用于Web程序,session 作用域表示该针对每一次 HTTP 请求都会产生一个新的 bean,同时该 bean 仅在当前 HTTP session 内有效.与request作用域一样,可以根据需要放心的更改所创建实例的内部状态,而别的 HTTP session 中根据 userPreferences 创建的实例,将不会看到这些特定于某个 HTTP session 的状态变化。当HTTP session最终被废弃的时候,在该HTTP session作用域内的bean也会被废弃掉。

xml文件配置:

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/> 

也可以使用注解的方式配置:

@Service
@Scope("session")
public class ServiceImpl{

}

globalSession

global session 作用域类似于标准的 HTTP session 作用域,不过仅仅在基于 portlet 的 web 应用中才有意义。Portlet 规范定义了全局 Session 的概念,它被所有构成某个 portlet web 应用的各种不同的 portle t所共享。在global session 作用域中定义的 bean 被限定于全局portlet Session的生命周期范围内。

xml文件配置:

<bean id="user" class="com.foo.Preferences "scope="globalSession"/> 

也可以使用注解的方式配置:

@Service
@Scope("globalSession")
public class ServiceImpl{

}

五种作用域比较

在这里插入图片描述

Bean的生命周期

对于普通的java对象来说,它们的生命周期就是:实例化——》不再使用的时候通过垃圾回收机制进行回收。

Spring中Bean 的生命周期概括起来就是 4 个阶段:

  1. 实例化(Instantiation)
  2. 属性赋值(Populate)
  3. 初始化(Initialization)
  4. 销毁(Destruction)

Spring 容器可以管理 singleton 作用域 Bean 的生命周期,在此作用域下,Spring 能够精确地知道该 Bean 何时被创建,何时初始化完成,以及何时被销毁。对于 prototype 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。每次客户端请求 prototype 作用域的 Bean 时,Spring 容器都会创建一个新的实例,并且不会管那些被配置成 prototype 作用域的 Bean 的生命周期。

Bean的初始化过程

在这里插入图片描述

  • BeanDefinitionReader读取Resource所指向的配置文件资源,然后解析配置文件。配置文件中每一个解析成一个BeanDefinition对象,并保存到BeanDefinitionRegistry中;
    容器扫描BeanDefinitionRegistry中的BeanDefinition;调用InstantiationStrategy进行Bean实例化的工作;使用BeanWrapper完成Bean属性的设置工作;
  • 单例Bean缓存池:Spring 在DefaultSingletonBeanRegistry类中提供了一个用于缓存单实例 Bean 的缓存器,它是一个用HashMap实现的缓存器,单实例的Bean以beanName为键保存在这个HashMap中。

BeanFactory中Bean的生命周期

在这里插入图片描述

ApplicationContext中Bean的生命周期

在这里插入图片描述

BeanFactory、ApplicationContext对比

这里说的Bean的生命周期讲的都是作用域为singleton

  • ApplicationContext会利用Java反射机制自动识别出配置文件中定义的BeanPostProcessor、 InstantiationAwareBeanPostProcesso 和BeanFactoryPostProcessor后置器,并自动将它们注册到应用上下文中。而BeanFactory需要在代码中通过手工调用addBeanPostProcessor()方法进行注册
  • ApplicationContext在初始化应用上下文的时候就实例化所有单实例的Bean。而BeanFactory在初始化容器的时候并未实例化Bean,直到第一次访问某个Bean时才实例化目标Bean。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值