实例化Bean
后面有加上去的另一篇博客,前面这部分跟上一篇内容重复
Spring IoC容器如何实例化Bean呢?传统应用程序可以通过new和反射方式进行实例化Bean。而Spring IoC容器则需要根据Bean定义里的配置元数据使用反射机制来创建Bean。在Spring IoC容器中根据Bean定义创建Bean主要有以下几种方式:
一、使用构造器实例化Bean:这是最简单的方式,Spring IoC容器即能使用默认空构造器也能使用有参数构造器两种方式创建Bean,如以下方式指定要创建的Bean类型:
使用空构造器进行定义,使用此种方式,class属性指定的类必须有空构造器
java代码:
- <bean name="bean1" class="cn.javass.spring.chapter2.HelloImpl2"/>
使用有参数构造器进行定义,使用此中方式,可以使用< constructor-arg >标签指定构造器参数值,其中index表示位置,value表示常量值,也可以指定引用,指定引用使用ref来引用另一个Bean定义,后边会详细介绍:
java代码:
- <bean name="bean2" class="cn.javass.spring.chapter2.HelloImpl2">
- <!-- 指定构造器参数 -->
- <constructor-arg index="0" value="Hello Spring!"/>
- </bean>
知道如何配置了,让我们做个例子的例子来实践一下吧:
(1)准备Bean class(HelloImpl2.java),该类有一个空构造器和一个有参构造器:
java代码:
- package cn.javass.spring.chapter2;
- public class HelloImpl2 implements HelloApi {
- private String message;
- public HelloImpl2() {
- this.message = "Hello World!";
- }
- Public HelloImpl2(String message) {
- this.message = message;
- }
- @Override
- public void sayHello() {
- System.out.println(message);
- }
- }
(2)在配置文件(resources/chapter2/instantiatingBean.xml)配置Bean定义,如下所示:
java代码:
- <!--使用默认构造参数-->
- <bean name="bean1" class="cn.javass.spring.chapter2.HelloImpl2"/>
- <!--使用有参数构造参数-->
- <bean name="bean2" class="cn.javass.spring.chapter2.HelloImpl2">
- <!-- 指定构造器参数 -->
- <constructor-arg index="0" value="Hello Spring!"/>
- </bean>
(3)配置完了,让我们写段测试代码(InstantiatingContainerTest)来看下是否工作吧:
java代码:
- @Test
- public void testInstantiatingBeanByConstructor() {
- //使用构造器
- BeanFactory beanFactory =
- new ClassPathXmlApplicationContext("chapter2/instantiatingBean.xml");
- HelloApi bean1 = beanFactory.getBean("bean1", HelloApi.class);
- bean1.sayHello();
- HelloApi bean2 = beanFactory.getBean("bean2", HelloApi.class);
- bean2.sayHello();
- }
二、使用静态工厂方式实例化Bean,使用这种方式除了指定必须的class属性,还要指定factory-method属性来指定实例化Bean的方法,而且使用静态工厂方法也允许指定方法参数,spring IoC容器将调用此属性指定的方法来获取Bean,配置如下所示:
(1)先来看看静态工厂类代码吧HelloApiStaticFactory:
java代码:
- public class HelloApiStaticFactory {
- //工厂方法
- public static HelloApi newInstance(String message) {
- //返回需要的Bean实例
- return new HelloImpl2(message);
- }
- }
(2)静态工厂写完了,让我们在配置文件(resources/chapter2/instantiatingBean.xml)配置Bean定义:
java代码:
- <!-- 使用静态工厂方法 -->
- <bean id="bean3" class="cn.javass.spring.chapter2.HelloApiStaticFactory" factory-method="newInstance">
- <constructor-arg index="0" value="Hello Spring!"/>
- </bean>
(3)配置完了,写段测试代码来测试一下吧,InstantiatingBeanTest:
java代码:
- @Test
- public void testInstantiatingBeanByStaticFactory() {
- //使用静态工厂方法
- BeanFactory beanFactory =
- new ClassPathXmlApplicationContext("chaper2/instantiatingBean.xml");
- HelloApi bean3 = beanFactory.getBean("bean3", HelloApi.class);
- bean3.sayHello();
- }
三、使用实例工厂方法实例化Bean,使用这种方式不能指定class属性,此时必须使用factory-bean属性来指定工厂Bean,factory-method属性指定实例化Bean的方法,而且使用实例工厂方法允许指定方法参数,方式和使用构造器方式一样,配置如下:
(1)实例工厂类代码(HelloApiInstanceFactory.java)如下:
java代码:
- package cn.javass.spring.chapter2;
- public class HelloApiInstanceFactory {
- public HelloApi newInstance(String message) {
- return new HelloImpl2(message);
- }
- }
(2)让我们在配置文件(resources/chapter2/instantiatingBean.xml)配置Bean定义:
java代码:
- <!—1、定义实例工厂Bean -->
- <bean id="beanInstanceFactory"
- class="cn.javass.spring.chapter2.HelloApiInstanceFactory"/>
- <!—2、使用实例工厂Bean创建Bean -->
- <bean id="bean4"
- factory-bean="beanInstanceFactory"
- factory-method="newInstance">
- <constructor-arg index="0" value="Hello Spring!"></constructor-arg>
- </bean>
(3)测试代码InstantiatingBeanTest:
java代码:
- @Test
- public void testInstantiatingBeanByInstanceFactory() {
- //使用实例工厂方法
- BeanFactory beanFactory =
- new ClassPathXmlApplicationContext("chapter2/instantiatingBean.xml");
- HelloApi bean4 = beanFactory.getBean("bean4", HelloApi.class);
- bean4.sayHello();
- }
通过以上例子我们已经基本掌握了如何实例化Bean了,大家是否注意到?这三种方式只是配置不一样,从获取方式看完全一样,没有任何不同。这也是Spring IoC的魅力,Spring IoC帮你创建Bean,我们只管使用就可以了,是不是很简单。
另一篇博文https://www.cnblogs.com/1693977889zz/p/8146563.html
本文主要介绍四种实例化bean的方式(注入方式) 或者叫依赖对象实例化的四种方式。上面的程序,创建bean 对象,用的是什么方法 ,用的是构造函数的方式 (Spring 可以在构造函数私有化的情况下把类对象创建出来)
常用的创建方式有以下四种:
1) setter 方法
2) 构造函数
3) 静态工厂
4) 实例工厂
一、用 setter 方式
这种方式上面没有提到
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();
}
}
//配置文件
<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();
二、构造函数
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);
}
//配置文件
<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" />可是最下面的userDao_name不是没有像userInfo_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" />
//测试
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
UserAction action=(UserAction)ctx.getBean("userAction_name");
action.execute();
三、静态工厂方式
//工厂,用来生成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;
}
}
//配置文件
<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" />
//测试
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
UserAction action=(UserAction)ctx.getBean("userAction_name");
action.execute();
四、实例工厂
//工厂 =>
public class UserDaoFactory {
//这个方法不是静态的
public IUserDao createUserDaoInstance(){
return new UserDaoOracleImpl();
}
}
//配置文件
<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" />