@Test
public void test01(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
//当程序执行完这条代码,也就是读取完xml配置文件,对象就被创建,而且多次创建的对象为不同个对象
UserDao userDao1 = (UserDao) app.getBean("userDao");
UserDao userDao2 = (UserDao) app.getBean("userDao");
System.out.println(userDao1);
System.out.println(userDao2);
}
}
```
![在这里插入图片描述](https://img-blog.csdnimg.cn/70108d2ce2c84e388c1474fa6b8a5776.png#pic_center)
Bean的生命周期:
* 对象创建:当使用对象时,创建新的对象实例
* 对象运行:只要对象在使用中,就一直活着
* 对象销毁:对象长时间不使用,就会被JAVA的垃圾回收器回收了
Bean实例化的三种方式:
- 无参构造方法实例化
- 工厂静态方法实例化
- 工厂实例方法实例化
2.1、无参构造方法实例化
<bean id="userDao" class="com.kang.impl.UserDaolmpl"></bean>
上述测试代码中所有的Bean实例化均为无参构造方法
2.2、工厂静态方法实例化
public class UserDaolmplFactory {
public static UserDaolmpl CreateUserDao(){
return new UserDaolmpl();
}
}
<bean id="userDao" class="com.kang.factory.UserDaolmplFactory" factory-method="CreateUserDao"></bean>
只需要在xml文件中,用factory-method告诉spring框架这是一个工厂模式并且工程的方法是CreateUserDao,那么spring框架仍然会返回一个Bean的实例化
spring框架会先找到com.kang.factory.UserDaolmplFactory,然后调用CreateUserDao这个静态方法,即可返回一个UserDao对象
并且java代码不需要有任何修改
2.3、工厂实例方法实例化
在工厂静态方法实例化的实现中,由于工厂里的方法是静态的,所以不需要创建工厂实例化对象,但是在如果工厂创建对象的方法不是静态的,那应该怎么办?
<bean id="factory" class="com.kang.factory.UserDaolmplFactory"></bean>
<bean id="userDao" factory-bean="factory" factory-method="CreateUserDao"></bean>
- 首先先创建id为factory的bean,让它返回一个工厂的对象
- 然后创建一个id为userDao的bean,在当中指明factory-bean(工厂的bean)的id,然后还有工厂创建对象的方法
- 同样,Java代码不需要修改
Bean可以由程序猿指定初始化和销毁的方法,只需要在xml配置文件的对应bean中加入以下标签
- init-method:指定类中的初始化方法名称
- destroy-method:指定类中的销毁方法名称
<bean id="userDao" class="com.kang.impl.UserDaolmpl" init-method="init" destroy-method="destroy"></bean>
package com.kang.impl;
import com.kang.UserDao;
public class UserDaolmpl implements UserDao {
public UserDaolmpl(){
System.out.println("创建对象");
}
@Override
public void save() {
System.out.println("save running......");
}
//初始化方法
public void init(){
System.out.println("初始化。。。。");
}
//销毁方法
public void destroy(){
System.out.println("销毁.....");
}
}
测试代码
public class SpringTest {
@Test
public void test01(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao1 = (UserDao) app.getBean("userDao");
System.out.println(userDao1);
((ClassPathXmlApplicationContext)app).close();
}
}
问题引入:
- 创建 UserService,UserService 内部在调用 UserDao的save() 方法
public class UserServiceImpl implements UserService {
@Override
public void save() {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) app.getBean("userDao");
userDao.save();
}
}
- 将 UserServiceImpl 的创建权交给 Spring
```
<bean id="userDao" class="com.kang.impl.UserDaolmpl"></bean>
<bean id="userService" class="com.kang.impl.UserServiceImpl"></bean>
```
- 从 Spring 容器中获得 UserService 进行操作
@Test
public void test02(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) app.getBean("userService");
userService.save();
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gT469oAN-1645704192217)(Spring入门.assets/image-20220224093008916.png)]
上述做法是将UserService实例和UserDao都存在spring容器中,然后再容器外部获取UserService实例和UserDao实例,然后在程序中进行结合
这当中存在的问题是:加载配置文件的时候,不需要getBean方法,配置文件的内容都被执行了,导致配置文件加载了多次,浪费资源
在test中,只需要UserService,但是UserDao也实例化了
因为UserService和UserDao都在Spring容器中,而最终程序直接使用的是UserService,所以可以在 Spring容器中,将UserDao设置到UserService内部。
要解决这个问题,就需要用到依赖引入
4.1、依赖引入的方式
通过构造方法和set方法实现将UserDao注入到UserService内部
4.1.1、set方法注入
set方法注入的前提,是要在UserServiceImpl里定义一个私有变量UserDao
然后通过set方法给该私有变量赋值
public class UserServiceImpl implements UserService {
private UserDao userDao;
@Override
public void save() {
userDao.save();
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
<bean id="userDao" class="com.kang.impl.UserDaolmpl"></bean>
<bean id="userService" class="com.kang.impl.UserServiceImpl">
<!--第一个userDao是指set方法后面的UserDao, 既setUserDao-->
<!--第二个userDao 是指上面的id的userDao的Bean实例化返回的UserDao对象-->
<property name="userDao" ref="userDao"/>
</bean>
注意:虽然两个userDao写法一样,但是两个userDao所代表的意思并不一样,注意区分
set方法注入还可以用P空间命名注入
首先引入P空间命名空间:
xmlns:p=“http://www.springframework.org/schema/p”
接着,修改注入方式:
<!--第一个userDao是指set方法后面的UserDao(首字母大写换小写), 既setUserDao-->
<!--第二个userDao 是指上面的id的userDao(对象引用)-->
<!--<property name="userDao" ref="userDao"/>-->
</bean>
spring的XML配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--<bean id="factory" class="com.kang.factory.UserDaolmplFactory"></bean>-->
<!--<bean id="userDao" factory-bean="factory" factory-method="CreateUserDao"></bean>-->
<!--<bean id="userDao" class="com.kang.impl.UserDaolmpl" init-method="init" destroy-method="destroy"></bean>-->
<bean id="userDao" class="com.kang.impl.UserDaolmpl"></bean>
<bean id="userService" class="com.kang.impl.UserServiceImpl" p:userDao-ref="userDao">
<!--第一个userDao是指set方法后面的UserDao, 既setUserDao-->
<!--第二个userDao 是指上面的id的userDao-->
<!--<property name="userDao" ref="userDao"/>-->
</bean>
</beans>
4.1.2、通过构造方法注入
创建有参构造方法
package com.kang.impl;
import com.kang.dao.UserDao;
import com.kang.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ClassName UserServiceImpl
* @Description TODO
* @Author kang
* @Date 2022/2/24 上午 9:22
* @Version 1.0
*/
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
public UserServiceImpl() {
}
@Override
public void save() {
userDao.save();
}
}
配置spring的xml配置文件
<bean id="userDao" class="com.kang.impl.UserDaolmpl"></bean>
<bean id="userService" class="com.kang.impl.UserServiceImpl" >
<!--第一个userDao是指有参构造方法的参数-->
<!--第二个userDao是指引用对象,即上面的id属性-->
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
Java的测试类代码依然不用变
Bean的依赖注入的数据类型有很多种,除了上面的对象还支持普通数据类型,集合等可以在容器中进行注入
注入的三种基本数据类型
- 普通数据类型
- 引用数据类型
- 集合数据类型
上述对对象的操作就是对引用数据类型的依赖注入
5.1、普通数据类型的注入
public class UserServiceImpl implements UserService {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void save() {
System.out.println("name = " + name);
System.out.println("age = " + age);
}
}
<bean id="userService" class="com.kang.impl.UserServiceImpl">
<property name="name" value="小明"></property>
<property name="age" value="18"></property>
</bean>
注意:ref 和 value的使用场景不一样
- ref:对象引用
- value:普通数据
5.2、集合数据类型(List< String >)的注入
package com.kang.impl;
import com.kang.dao.UserDao;
import com.kang.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class UserServiceImpl implements UserService {
List<String> list;
public void setList(List<String> list) {
this.list = list;
}
@Override
public void save() {
System.out.println(list);
}
}
<bean id="userService" class="com.kang.impl.UserServiceImpl">
<property name="list">
<list>
<value>华为</value>
<value>小米</value>
<value>苹果</value>
</list>
</property>
</bean>
上述是集合中为普通数据类型的案例
5.3、集合数据类型(List< User >)的注入
package com.kang.poj;
/**
* @ClassName User
* @Description TODO
* @Author kang
* @Date 2022/2/24 下午 4:29
* @Version 1.0
*/
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.kang.impl;
import com.kang.poj.User;
import com.kang.service.UserService;
import java.util.List;
public class UserServiceImpl implements UserService {
List<User> list;
public void setList(List<User> list) {
this.list = list;
}
@Override
public void save() {
System.out.println(list);
}
}
<bean id="user1" class="com.kang.poj.User">
<property name="name" value="小红"></property>
<property name="age" value="18"></property>
</bean>
<bean id="user2" class="com.kang.poj.User">
<property name="name" value="小明"></property>
<property name="age" value="20"></property>
</bean>
<bean id="userService" class="com.kang.impl.UserServiceImpl">
<property name="list">
<list>
<ref bean="user1"/>
<ref bean="user2"/>
</list>
</property>
</bean>
在配置文件中首先先要配置两个bean实例化的对象,然后将他们放到集合中
5.4、集合数据类型(Map< String, User >)的注入
将5.3的List集合改为Map集合,接着spring的XML文件配置修改为以下
<bean id="userService" class="com.kang.impl.UserServiceImpl">
<property name="list">
<map>
<entry key="第一个人" value-ref="user1"/>
<entry key="第二个人" value-ref="user2"/>
</map>
</property>
</bean>
### 最后
现在正是金三银四的春招高潮,前阵子小编一直在搭建自己的网站,并整理了全套的**【一线互联网大厂Java核心面试题库+解析】:包括Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等**
![image](https://img-blog.csdnimg.cn/img_convert/46f6410e41aab6176d9085f452fa8a76.webp?x-oss-process=image/format,png)
class="com.kang.poj.User">
<property name="name" value="小明"></property>
<property name="age" value="20"></property>
</bean>
<bean id="userService" class="com.kang.impl.UserServiceImpl">
<property name="list">
<list>
<ref bean="user1"/>
<ref bean="user2"/>
</list>
</property>
</bean>
在配置文件中首先先要配置两个bean实例化的对象,然后将他们放到集合中
5.4、集合数据类型(Map< String, User >)的注入
将5.3的List集合改为Map集合,接着spring的XML文件配置修改为以下
<bean id="userService" class="com.kang.impl.UserServiceImpl">
<property name="list">
<map>
<entry key="第一个人" value-ref="user1"/>
<entry key="第二个人" value-ref="user2"/>
</map>
</property>
</bean>
### 最后
现在正是金三银四的春招高潮,前阵子小编一直在搭建自己的网站,并整理了全套的**【一线互联网大厂Java核心面试题库+解析】:包括Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等**
[外链图片转存中...(img-9AHRJQJy-1714471989167)]
> **本文已被[CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/topics/618154847)收录**