在spring中,不再需要通过传统的方式创建,而是根据注解或者xml将类直接解析成bean,本文讲讲解关于bean的一些知识点。
Spring容器集中管理Bean的实例化,Bean实例可以通过BeanFactory的getBean(String beanid)方法得到。BeanFactory是一个工厂,程序只需要获取BeanFactory引用,即可获得Spring容器管理全部实例的引用。程序不需要与具体实例的实现过程耦合。大部分Java EE应用里,应用在启动时,会自动创建Spring容器,组件之间直接以依赖注入的方式耦合,甚至无须主动访问Spring容器本身。
1.基于xml的半定义(需要定义setter方法)
素可以定义 一个Bean实例,每一个Bean对应Spring容器里的一个Java实例定义Bean时通常需要指定两个属性。
Id:确定该Bean的唯一标识符,容器对Bean管理、访问、以及该Bean的依赖关系,都通过该属性完成。Bean的id属性
在Spring容器中是唯一的。
Class:指定该Bean的具体实现类。注意这里不能使接口。通常情况下,Spring会直接使用new关键字创建该Bean的实
例,因此,这里必须提供Bean实现类的类名。
当我们在配置文件中通过
类中必须有 一个无参构造器。
示例:
在applicationContext.xml中配置bean信息
2.基于注解的bean定义(不需要提供setter方法)
Spring为此提供了四个注解,这些注解的作用与上面的XML定义bean效果一致,在于将组件交给Spring容器管理。
组件的名称默认是类名(首字母变小写),也可以自己修改:
@Component:当对组件的层次难以定位的时候使用这个注解
@Controller:表示控制层的组件
@Service:表示业务逻辑层的组件
@Repository:表示数据访问层的组件
示例:
注解定义bean
//不知道该组件属于什么层次时,可以直接使用该注解@Component
@Component("address")
public class Address{
private Integer id;
//对于非bean id时的注入直接用@Value赋值
@Value("湖北省黄石市阳新县黄双口镇金星村")
private String name;
public String getName() {
return name;
}
}
//不知道该组件属于什么层次时,可以直接使用该注解@Component
@Component("user")
public class Teacher {
//对于非bean id时的注入直接用@Value赋值
@Value("25")
private Integer age;
//对于非bean id时的注入直接用@Value赋值
@Value("石破天")
private String name;
//对于bean id类型使用@Resource注解进行注入
@Resource
private Address address;
public Integer getAge() {
return name;
}
public String getName() {
return name;
}
}
applicationContext.xml 中添加一下配置信息。
3.基于Java类的bean定义(需要提供setter方法)
@Configuration
public class BeansConfiguration {
@Bean
public Student student(){
Student student=new Student();
student.setName("张三");
student.setTeacher(teacher());
return student;
}
@Bean
public Teacher teacher(){
Teacher teacher=new Teacher();
teacher.setName("李四");
return teacher;
}
}
当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。
Spring支持5种作用域:
Singleton:单例模式。在整个SpringIoC容器中,使用singleton定义的Bean将只有一个实例,这是默认的配置。
Prototype:原型模式。每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实
例。
request:对于每次HTTP请求,使用request定义的Bean都将产生一个新的实例,即每次HTTP请求都会产生不同
的Bean实例。当然只有在WEB应用中使用Spring时,该作用域才真正有效。
session:对于每次HTTPSession,使用session定义的Bean都将产生一个新的实例时,即每次HTTP Session都将
产生不同的Bean实例。同HTTP一样,只有在WEB应用才会有效。
global session:每个全局的HTTPSession对应一个Bean实例。仅在portlet Context的时候才有效。
比较常用的singleton和prototype。如果一个Bean实例被设置为singleton,那么每次请求该
Bean 时都会获得相同的实例。容器负责跟踪Bean实例的状态,负责维护Bean实例的生命
周期行为。如果一个Bean实例被设置为prototype,那么每次请求该di的Bean,Spring都会
创建一个新的Bean实例返回给程序,在这种情况下,Spring容器仅仅使用new关键字创建
Bean实例,一旦创建成功,容器将不会再跟踪实例,也不会维护Bean实例的状态。
如果我们不指定Bean的作用域,则Spring会默认使用singleton作用域。设置Bean的作用域是通过scope属性来指
定。 可以接受Singleton、prototype、request、session、global session 5个值。
Spring支持如下三种方式创建Bean
1:调用构造器创建Bean
调用构造方法创建Bean是最常用的一种情况Spring容器通过new关键字调用构造器来创建Bean实例,通过class
属性指定Bean实例的实现类,也就是说,如果使用构造器创建Bean方法,则
其实Spring容器也就是相当于通过实现类new了一个Bean实例。调用构造方法创建Bean实例,通过名字也可以
看出,我们需要为该Bean类提供无参数的构造器。
因为是通过构造函数创建Bean,因此我们需要提供无参数构造函数,另外我们定义了一个name属性,并提供了
setter方法,Spring容器通过该方法为name属性注入参数。
示例:(以xml形式定义bean)
package com.spring;
public class User implements IUser {
private String name;
private Integer age;
public User(){
System.out.println("通过spring会通过new关键字调用无参构造器实例化");
}
//提供setter方法,在xml中定义bean时,将调用该方法给对应的属性赋值即所谓的依赖注入
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
}
applicationContext.xml
2:调用静态工厂方法创建Bean
通过静态工厂创建Bean是把创建Bean的任务交给了静态工厂,而不是
构造函数,这个静态工厂就是一个Java类,在使用静态工厂创建Bean需要在
静态工厂是一个Java类,那么该class属性指定的就是该工厂的实现类,而不再是Bean的实现类,告诉Spring
这个Bean应该由哪个静态工厂创建,另外我们还需要添加factory-method属性来指定由工厂的哪个方法来创建
Bean实例,因此使用静态工厂方法创建Bean实例需要为
class:指定静态工厂的实现类,告诉Spring该Bean实例应该由哪个静态工厂创建(指定工厂地址)
factory-method:指定由静态工厂的哪个方法创建该Bean实例(指定由工厂的哪个车间创建Bean)
如果静态工厂方法需要参数,则使用
示例:
步骤: 1.定义一个接口 Person
2.定一个实现Person接口的实现类HuBeiMan
3.定义另外一个实现Person接口的实现类ShenZenMan
4.定义一个静态工厂,主要是用来创建实体类
5.xml定义bean(创建bean实例,实际实例由静态工厂创建)
1
public interface Person{
public void say();
}
2
public class HuBeiMan implements Person{
private String msg;
//提供setter方法
public void setMsg(String msg)
{
this.msg = msg;
}
@Override
public void say(){
System.out.println("湖北人说的方言很难懂");
}
}
public class ShenZenMan implements Person{
private String msg;
//提供setter方法
public void setMsg(String msg)
{
this.msg = msg;
}
@Override
public void say(){
System.out.println("深圳人大部分来自全国各地");
}
}
3
//在xml中定义bean时,需要创建什么类的bean实例,可以class直接指向静态工厂类
public class PersonFactory {
//调用对应方法,并传递对应参数
public static Person getPerson(String arg) {
根据指定name来获取对应的实例,该name在xml中
if(arg.equalsIgnoreCase("chinese"))
{
return new Chinese();
}
else
{
return new American();
}
}
}
4
3:调用实例工厂方法创建Bean
静态工厂通过class指定静态工厂实现类然后通过相应的方法创建即可,调用实例工厂则需要先创建该工厂的Bean
实例,然后引用该实例工厂Bean的id创建其他Bean,在实例工厂中通过factory-bean指定工厂Bean的实例,在调
用实例化工厂方法中,不用在
实例化工厂的方法,创建Bean实例。调用实例化工厂需要为
factory-bean :该属性指定工厂Bean的id
factory-method:该属性指定实例工厂的工厂方法。
示例:在上一种方法示例的基础上修改对应的配置文件
实例工厂创建Bean和调用静态工厂的区别
调用实例工厂将工厂单独拿了出来(先实例化工厂)创建一个工厂Bean,通过工厂
实现类,然后再需要创建其他Bean时,只需要在该
是有哪个实例工厂的哪个方法创建就可以了,放在现实生活中就是:我们先找一个地方创建一个工厂,id指定工
厂注册名字(xxx有限公司),class指定公司所在地,工厂里面有车间(创造其他Bean的方法),那好有了工厂
我们再需要创建其他Bean时,只需要指定这个Bean是由,哪个工厂的哪个车间创建的即可,也就是只需要在该
1 注入bean
在Spring中,注入依赖对象可以采用手工装配或自动装配,一般是使用手工注入,因为自动装配容易出现未知问题,
自动装配是在配置文件中实现的,不用再配置文件中写
如下:
autowire属性值有:
no:默认的。默认为不自动装配
byName:根据属性名称自动进行查找与该name相同的bean并装配,如果没有找到,则属性值为null
byType:根据属性类型自动进行装配,如有多个会报异常,如果没有找到,则属性值为null
以下三种方式都属于手工装配。
1.1 setter属性注入
①ref标识符
② value
或者
湖北省黄石市阳新县黄双口镇金星村
1.2 使用构造器注入
示例:
第一步:定义的类符合以下要求
public class User{
//声明依赖对象
private Address address= null;
//生成无参构造函数
public User(){
super;
}
//生成有参构造函数
public User(Address address){
super;
this.address=address;
}
}
第二步:在配置文件中配置该类的bean,并配置构造器,关键元素节点
性:
index是索引,指定注入的属性,从0开始,如:0代表personDao,1代表str属性;
type是指该属性所对应的类型,如Persondao对应的是com.aptech.dao.PersonDAO;
ref 是指引用的依赖对象;
value 当注入的不是依赖对象,而是基本数据类型时,就用value;
1.3 使用注解注入
在类的内部定义依赖属性上加上注解,并在配置文件中加上
信息,该配置信息配置隐式的注册了多个对注释进行解析的处理器:器AutowiredAnnotationBeanPostProcessor、
CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor等。
注解:
@Resource:默认按类型装配
用@Autowired为上面的代码UserDAO接口的实例对象进行注解,它会到Spring容器中去寻找与
UserDao对象相匹配的类型,如果找到该类型则将该类型注入到userdao字段中;
@Autowired:它先会根据指定的name属性去Spring容器中寻找与该名称匹配的类型。
例如:@Resource(name="userDao"),如果没有找到该名称,则会按照类型去寻找,找到之后,
会对字段userDao进行注入。
示例:
第一步:在依赖属性上加上注解
//不需要setter方法
public class UserServiceImpl implements UserService {
@Resource(name="userDao") //或者@AutoWired
private UserDAO userDao = null;
public void addUser() {
this.userDao.addUser();
}
}
第二步:bean的定义(有三种,这里以xml定义为例)
第四步:在applicationContext.xml中加上
2 集合注入
2.1 list
1
2
3
2.2 map
2.3 props
value1
value2
2.4 set
< property name ="interest" >
<!--注入时调用的setter方法的参数类型为Set类型时-->
< set >
< value > 唱歌 value >
< value > 跳舞 value >
< value > 书法 value >
set >
property >