目录
一、spring容器之bean的实例化。
(1)"bean"基本概念。
(2)spring-bean实例化的几种方式。
二、spring容器使用"构造方法"的方式实例化bean。
(1)无参构造方法实例化bean。
(2)有参构造方法实例化bean。
1、新建一个类"Student",并交给spring容器管理。
2、使用子标签<constructor-arg>完成bean配置。
3、有参构造方法的参数为多个时(index与value)。
4、标签内<constructor-arg>使用"name"属性。
<1>spring-context版本过高需要添加type属性。
<2>spring-context版本中等不需要添加type属性。
(3)使用场景。
-
本篇博客的主要内容是使用(构造方法或静态工厂)实现spring-bean实例化。
一、spring容器之bean的实例化。
(1)"bean"基本概念。
- spring框架中总是有"bean"这个词出现!它的本质上就是对象。
- spring容器管理的对象叫bean。
- 在Java基础的学习中,创建对象通常都是使用new+构造方法。
- 对应spring容器来说,它也是可以通过构造方法完成bean的创建!
(2)spring-bean实例化的几种方式。
二、spring容器使用"构造方法"的方式实例化bean。
(1)无参构造方法实例化bean。
- 注意:每个类会默认提供一个无参构造方法。就算未写,也是调用了无参构造方法。但如果手动提供了有参构造方法,一般一定记得再手动提供无参构造方法。
- spring容器是可以通过无参构造方法实例化bean的。下面通过demo(案例)进行演示。
- spring的简单demo项目的结构组成与介绍。
- spring配置文件。(目前只配置了"UserDaoImpl"的bean)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--生产UserDao实现类的对象--> <bean id="userDao" class="com.fs.dao.impl.UserDaoImpl"></bean> </beans>
UserDao接口。
package com.fs.dao; //UserDao接口 public interface UserDao { void add(); }
UserDaoImpl实现类。
package com.fs.dao.impl; import com.fs.dao.UserDao; //UserDao接口的实现类 public class UserDaoImpl implements UserDao { //手动添加无参构造方法 public UserDaoImpl() { System.out.println("UserDaoImpl无参构造方法执行了"); } //实现UserDao接口中的add方法 @Override public void add() { System.out.println("UserDaoImpl执行了add方法"); } }
程序的测试类。
package com.fs.test; import com.fs.dao.impl.UserDaoImpl; import org.springframework.context.support.ClassPathXmlApplicationContext; //运行测试程序 public class MainApp { public static void main(String[] args) { //使用IoC容器(ApplicationContext)获取spring容器管理的bean对象 //1.创建容器对象。实例化时参数指定对应的配置文件 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml"); //2.通过<bean>标签的唯一标识id获取对应UserDao接口的实现类"UserDaoImpl"的实例对象 Object obj = context.getBean("userDao"); //3.强制类型转换 UserDaoImpl userDao = (UserDaoImpl)obj; userDao.add(); } }
demo的运行结果。
如果将无参构造方法public设置成private权限,spring容器还能够帮忙实例化对象吗?
在以前的new+构造方法时显然是不能够的!但是spring容器却可以!无论提供的无参构造方法是公共的还是私有的,spring容器都能够调用到该无参构造方法。
这就是涉及到spring容器内部底层工作原理——反射机制。这个后面再详细学习,现在只需要知道spring容器是可以拿构造方法实例化bean就行了。
是否可以直接不做任何操作让spring容器使用有参构造方法实例化bean?
答案是不行的。因为spring创建的bean的时候是默认调用无参构造方法。
- 查看spring的报错信息可以一层一层的往上分析。
(2)有参构造方法实例化bean。
package com.fs.a; public class Student { }
- 上面得demo中spring容器默认使用无参构造方法实例化bean时。当把无参构造方法变成有参构造方法,不仅仅程序中会报错,xml文件中也会报错!
1、新建一个类"Student",并交给spring容器管理。
package com.fs.a; public class Student { //类中提供一个有参构造方法 public Student(String name) { System.out.println("参数是:"+name); } }
- 这时像原先通过无参构造方法完成bean实例化的spring配置文件已经报错!因为此时只提供了有参构造方法,而未提供无参构造方法。
2、使用子标签<constructor-arg>完成bean配置。
- <bean>标签中的子标签<constructor-arg>用于指定构造函数参数。这样以便在spring容器创建bean时传递给相应的构造函数。
- "value"属性的值就是给对应有参构造方法的参数变量赋值。
<!--配置Student类的对象--> <bean id="student" class="com.fs.a.Student"> <constructor-arg value="zhangsan"/> </bean>
- 测试类MainApp02代码。也是一样的使用ApplicationContext容器的加载spring配置文件与getBean()拿取spring容器管理的对象(Student类)。
package com.fs.test; import com.fs.a.Student; import org.springframework.context.support.ClassPathXmlApplicationContext; //测试类2 public class MainApp02 { public static void main(String[] args) { //使用IoC容器(ApplicationContext)获取spring容器管理的bean对象 //1.创建容器对象。实例化时参数指定对应的配置文件 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml"); //2.通过<bean>标签的唯一标识id获取对应UserDao接口的实现类"UserDaoImpl"的实例对象 Object obj = context.getBean("student"); //3.强制类型转换 Student student = (Student)obj; System.out.println(student); } }
- 测试运行!
3、有参构造方法的参数为多个时(index与value)。
- 修改Student类的有参构造方法。
package com.fs.a; public class Student { //类中提供一个有参构造方法 public Student(String name,int age) { System.out.println("参数是:"+name+",年龄是:"+age); } }
- 此时spring的配置文件又出现了报错!
- 在子标签<constructor-arg>中除了给"value"属性赋值外,还需要指定参数的位置(索引)属性"index"的值,这样一一对应了有参构造方法的参数值。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--生产UserDao实现类的对象 <bean id="userDao" class="com.fs.dao.impl.UserDaoImpl"></bean>--> <!--配置Student类的对象--> <bean id="student" class="com.fs.a.Student"> <constructor-arg index="0" value="李四"/> <constructor-arg index="1" value="18"/> </bean> </beans>
- 此时再运行测试类(MainApp02)程序查看结果。
- 若给int类型的age赋值一个字符串,spring配置文件中也会报错提示。
- 删去<bean>标签内对应的配置<constructor-arg>。就会报错(没有默认的无参构造:No default constructor found)
4、标签<constructor-arg>内使用"name"属性。
- 用"name"属性指定有参构造方法的参数,就不需要像"index"属性那样需要按顺序去赋值"value"属性。
<1>spring-context版本过高需要添加type属性。
- 如依赖导入spring-context(6.2.0)。
- 在直接指定name="age" value="18" 时无法解析成功!出现异常String无法——>int。
<!--https://mvnrepository.com/artifact/org.springframework/spring-context--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>6.2.0</version> </dependency>
解决方法:添加type属性,指定value参数值是int类型。
<2>spring-context版本中等不需要添加type属性。
- 如依赖导入spring-context(5.3.18)。
- 也许是版本低的原因,支持以前的写法(直接使用属性"name"指定对应有参构造方法里的参数,再通过value属性赋值)
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.18</version> </dependency>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--生产UserDao实现类的对象 <bean id="userDao" class="com.fs.dao.impl.UserDaoImpl"></bean>--> <!--配置Student类的对象--> <bean id="student" class="com.fs.a.Student"> <constructor-arg name="age" value="18"/> <constructor-arg name="name" value="wangwu"/> </bean> </beans>
(3)使用场景。
- 当我们使用第三方的技术时,将它们也交给spring容器进行管理。学会了使用无参构造与有参构造方法实例化bean时,就可以直接使用spring容器管理并获得bean对象。