案例引入
public class Users { public void add(){ System.out.println("add方法"); } } // ============================================================================ public class Test { public static void main(String[] args) { // ClassPathXmlApplicationContext 读取的地址是 src 目录下的 // FileSystemXmlApplicationContext 读取的是带 盘符的地址 ApplicationContext context = new ClassPathXmlApplicationContext("com/guigu/beans.xml"); Users user = context.getBean("user", Users.class); System.out.println(user); user.add(); } } // ============================================================================ <?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"> <bean id="user" class="com.guigu.Users"></bean> </beans>
IOC 接口
spring 提供 IOC容器 实现两种方式:(两个接口)
BeanFactory
IOC容器基本实现,是spring内部的使用接口,不提供开发人员进行操作;加载配置文件时候不会去创建对象,在获取(使用)对象时才去创建。
ApplicationContext
它是BeanFactory
的子接口,提供了更多更强大的功能,一般由开发人员使用;加载配置文件时,会把配置文件中的对象进行创建
ApplicationContext
的实现类主要是:
ClassPathXmlApplicationContext
读取配置文件时,是从 src 目录下读取的FileSystemXmlApplicationContext
读取配置文件时,需要从带盘符的地址读取
IOC 具体操作
bean管理
spring 创建对象
spring 注入属性
bean 管理的两种实现方式为:
基于xml配置文件的方式实现
基于注解的方式实现
基于 xml 创建对象
使用bean标签,在里面添加对应的属性,可以创建对象
<bean id="user" class="com.guigu.Users"></bean>
id属性:给对象取得别名
class属性:要创建对象的类的全路径
name属性:与id属性是一样的,可以添加特殊符号(与 strut 配合)
创建对象时,默认执行的是无参的构造方法
基于 xml 注入属性
DI:依赖注入,就是注入属性
- 使用set方法注入
// ====Java 类中============================================================================ public class Users { private String name; private Integer age; public void setName(String name) { this.name = name; } public void setAge(Integer age) { this.age = age; } } // ====xml文件中============================================================================ <bean id="user" class="com.guigu.Users"> <!-- name中是属性的名称 value里是你要注入的值--> <property name="name" value="张三"></property> <property name="age" value="22"></property> </bean>
- 使用有参构造注入
// ====Java 类中==================================================================== private String name; private Integer age; public Users(String name, Integer age) { this.name = name; this.age = age; } // ====xml文件中===================================================================== <bean id="order" class="com.guigu.Users"> <constructor-arg name="name" value="里斯"></constructor-arg> <constructor-arg name="age" value="33"></constructor-arg> // 也可以用 index 代替 name </bean>
p 名称空间注入
使用p 名称空间注入时,实体类中必须有set方法,其实其本质还是set注入
<?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="order" class="com.guigu.Users" p:name="王五" p:age="22"> </bean> </beans>
IOC操作Bean管理
- 字面量
-
- null值
<null/>
- 属性包含特殊符号
- 把特殊符号进行转义
< >
- 把特殊符号内容写到CDATA
<value> <![CDATA[ <<书名>> ]]> </value>
- null值
- 注入属性 - 外部 bean
通过server
调用dao
就叫做引入外部bean
public interface UsersDao { public void add(); } // ==================================================================================== public class UserDaoImpl implements UsersDao { @Override public void add() { System.out.println("UserDaoImpl 的 add 方法"); } } // ==================================================================================== public class UserService { private UsersDao usersDao; public void setUsersDao(UsersDao usersDao) { this.usersDao = usersDao; } public void add(){ System.out.println("UserService 的 add 方法"); usersDao.add(); } } // ==================================================================================== <?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="userService" class="com.guigu.service.UserService"> <property name="usersDao" ref="UserDaoImpl"> </property> </bean> <bean id="UserDaoImpl" class="com.guigu.dao.UserDaoImpl"></bean> </beans>
- 注入属性 - 内部 bean 和 级联赋值
<bean id="userService" class="com.guigu.service.UserService"> <property name="usersDao"> <bean id="UserDaoImpl" class="com.guigu.dao.UserDaoImpl"> </bean> </property> </bean>
级联赋值就是: 一对多的关系 ==》 部门和员工
<bean id="userService" class="com.guigu.service.UserService"> <property name="usersDao" ref="UserDaoImpl"> </property> </bean> <bean id="UserDaoImpl" class="com.guigu.dao.UserDaoImpl"></bean>
集合类型的属赋值
<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" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean> <!-- 数组类型属性注入--> <property name=""> <array> <value>第一元素</value> <value>第二元素</value> </array> </property> <!-- list 类型属性注入--> <property name=""> <list> <value>第一元素</value> <value>第二元素</value> </list> </property> <!-- map 类型属性注入--> <property name=""> <map> <entry key="java" value="java"></entry> <entry key="C++" value="C++"></entry> </map> </property> <!-- set 类型属性注入--> <property name=""> <set> <value>第一元素</value> <value>第二元素</value> <ref bean="对象的 id 值">加对象</ref> </set> </property> </bean> // ======= 使用 util 标签 ========================================================== <util:list id="booklist"> <value>第一元素</value> <value>第二元素</value> </util:list> <bean id="book" class="com.guigu.book"> <property name="list" ref="booklist"> </property> </bean>
IOC 操作 Bean 管理(FactoryBean)
- spring中一共有两种类型的bean,一种是普通的bean(就是我们自己创建的),另外一种就是内部的bean也叫工厂bean(FactoryBean)
- 普通bean特点:在配置文件中定义的类型,就是返回的类型
- 工厂bean的特点:在配置文件中定义bean的类型可以与返回的类型不一样
第一步:创建类,让这个类作为工厂bean,实现接口FactoryBean
第二步:实现接口里面的方法,在实现的方法中定义返回的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"> <bean id="myBean" class="cn.guili.MyBean"> </bean> </beans> // ================================================================================ public class MyBean implements FactoryBean<U_Book> { @Override public U_Book getObject() throws Exception { U_Book u_book = new U_Book("关谷神奇"); return u_book; } @Override public Class<?> getObjectType() { return null; } @Override public boolean isSingleton() { return FactoryBean.super.isSingleton(); } } // ================================================================================ public class U_Book { private String name; public U_Book(String name) { this.name = name; } public U_Book() { } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "U_Book{" + "name='" + name + '\'' + '}'; } } // ================================================================================ public class TestBean { @Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("cn/guili/beans_01.xml"); U_Book myBean = context.getBean("myBean", U_Book.class); System.out.println(myBean); } }
bean的作用域
- 在spring里面,设置创建bean实例是单实例还是多实例
- 在spring里面,默认情况下,bean是单实例对象
- 如何设置是单实例还是多实例
-
- 在bean标签中有个属性 scope 用于设置单实例还是多实例
-
-
- singleton 默认值,表示是单实例
- prototype 表示多实例
-
<bean id="myBean" class="cn.guili.MyBean" scope="singleton">
</bean>
ApplicationContext context = new ClassPathXmlApplicationContext("cn/guili/beans_01.xml");
U_Book myBean = context.getBean("myBean", U_Book.class);
U_Book myBean1 = context.getBean("myBean", U_Book.class);
System.out.println(myBean);
System.out.println(myBean1);
输出的结果:
cn.guili.U_Book@4fb0f2b9
cn.guili.U_Book@4fb0f2b9
===============================================================
<bean id="myBean" class="cn.guili.MyBean" scope="prototype">
</bean>
ApplicationContext context = new ClassPathXmlApplicationContext("cn/guili/beans_01.xml");
U_Book myBean = context.getBean("myBean", U_Book.class);
U_Book myBean1 = context.getBean("myBean", U_Book.class);
System.out.println(myBean);
System.out.println(myBean1);
输出的结果:
cn.guili.U_Book@5ffead27
cn.guili.U_Book@6356695f
注意:地址不一样证明是一个多实例对象,设置scope
值为prototype
时候,不是在加载spring
配置文件时候创建对象,而是在调用getBean
方法时,创建多实例对象
request 一次请求
session 一次对话
bean的生命周期
- 生命周期
-
- 从对象的创建到对象的销毁的过程
- bean生命周期
-
- 通过构造器创建bean实例(执行无参构造)
- 为bean的属性设置值,和对其他bean引用(调用set方法)
- 把bean实例传递bean后置处理器的方法
postProcessBeforeInitialization
- 调用bean的初始化的方法(需要进行配置初始化方法)
- 把bean实例传递bean后置处理器的方法
postProcessAfterInitialization
- bean可以使用了(对象获取到了)
- 当容器关闭的时候,调用bean的销毁方法(需要进行配置销毁的方法)
代码演示:
class Orders{
private String name;
public void setName(String name) {
this.name = name;
System.out.println("第二步,调用set方法 设置属性的值");
}
public Orders(){
System.out.println("第一步,执行无参构造创建实例");
}
public void initMethod(){
System.out.println("第三步,执行初始化方法");
}
public void destroyMethod(){
System.out.println("第五步,执行销毁方法");
}
}
<bean id="orders" class="cn.guili.Orders" init-method="initMethod" destroy-method="destroyMethod">
</bean>
ApplicationContext context = new ClassPathXmlApplicationContext("cn/guili/beans_01.xml");
Orders orders= context.getBean("orders", Orders.class);
// 获取对象
System.out.println("第四步,获取bean的实例对象");
System.out.println(orders);
// 销毁的方法
(ClassPathXmlApplicationContext)context.close();
- bean的后置处理器,bean 的生命周期一共有七步
// 创建类 public class Mybb implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("在初始化之前执行"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("在初始化之后执行"); return bean; } }
配置后置处理器
<bean id="myBean" class="cn.guili.Mybb"> </bean>
加载配置文件的时候,会将bean的实例创建,也会把后置处理器创建;当Mybb
这个类实现了BeanPostProcessor
接口后,spring
会将Mybb
当成后置处理器去执行,后置处理器会为当前的配置文件中的所有bean
都添加一个后置处理器的处理。
(笔记根据尚硅谷哔站视频所记)