1、Spring 容器加载的 3 种方式
public class ServiceTest {public static void main(String[] args) {
//Spring 容器加载有 3 种方式
// 第一种:ClassPathXmlApplicationContext ClassPath 类路径加载,指的就是 classes 路径
// 第一种:最常用,spring 的配置文件路径以后就直接放在 src
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// 第二种方式:文件系统路径获得配置文件【绝对路径】//ApplicationContext context = new FileSystemXmlApplicationContext("C:\\Users\\Desktop\\IDEAWorkspace\\spring-01\\src\\com\\rookie\\beans.xml");
// 第三种方式: 使用 BeanFactory(了解)
//String path = "C:\\Users\\Desktop\\IDEAWorkspace\\spring-01\\src\\com\\rookie\\beans.xml";
//BeanFactory factory = new XmlBeanFactory(new FileSystemResource(path));
//IUserService user = (IUserService) factory.getBean("userService");
//user.add();
IUserService user = (IUserService) context.getBean("userService");
user.add();}
}
Spring 内部创建对象的原理
a. 解析 xml 文件,获取类名,id, 属性等。
b. 通过反射,用类型创建对象。
c. 给创建的对象赋值。
2、BeanFactory 和 ApplicationContext 对比
BeanFactory 采取延迟加载,第一次 getBean 时才会初始化 Bean。
ApplicationContext 是即时加载,对 BeanFactory 扩展,提供了更多功能。
-
案例演示 (在第一次的代码基础上)
public class UserServiceImpl implements UserService { private String name; public void setName(String name) {this.name = name;} @Override public void add() {System.out.println("创建用户...." + name); } public UserServiceImpl(){System.out.println("UserServiceImpl() 调用了"); } }
public class ServiceTest {public static void main(String[] args) { //1. 加载 beans.xml 这个 spring 的配置文件, 内部就会创建对象 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); } }
控制台打印日志:UserServiceImpl() 调用了
public class ServiceTest {public static void main(String[] args) { String path = "C:\\Users\\Desktop\\IDEAWorkspace\\spring-01\\src\\com\\rookie\\beans.xml"; BeanFactory factory = new XmlBeanFactory(new FileSystemResource(path)); // 要使调用空参构造可以放开这段代码即可 // IUserService user = (IUserService) factory.getBean("userService"); } }
控制台没有打印日志,说明空参构造没有被调用。
放开上面注释的代码,即可调用空参构造,控制台打印日志:UserServiceImpl() 调用了。
2、Spring 容器装配 bean 的 3 种方式
所谓的装配 bean 就是在 xml 写一个 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 的三种方式,所谓的装配 bean 就是在 xml 写一个 bean 标签 -->
<!-- 第一种方式: new 实现类 -->
<bean id="userService1" class="com.example.demo.service.impl.UserServiceImpl">
<property name="name" value="zhangsan"></property>
</bean>
<!-- 第二种方式:通过静态工厂方法 -->
<bean id="userService2" class="com.example.demo.service.UserServiceFactory" factory-method="createUserService"/>
<!-- 第三种方式:通过实例工厂方法 -->
<bean id="factory2" class="com.example.demo.service.UserServiceFactory2"/>
<bean id="userService3" factory-bean="factory2" factory-method="createUserService"/>
</beans>
测试上面哪种 bean 装配方式,需要注释掉其他 bean 装配方式。
第一种上次已经讲过,现在只讲第二、三种案例。
public class UserServiceFactory {public static UserService createUserService() {return new UserServiceImpl();
}
}
=========================================================================================
public class UserServiceFactory2 {public UserService createUserService() {return new UserServiceImpl();
}
}
执行测试函数
public class ServiceTest {public static void main(String[] args) {
//new 对象
ApplicationContext context1 = new ClassPathXmlApplicationContext("beans.xml");
UserService userService1 = (UserService) context1.getBean("userService1");
userService1.add();
// 静态工厂
ApplicationContext context2 = new ClassPathXmlApplicationContext("beans.xml");
UserService userService2 = (UserService) context2.getBean("userService2");
userService2.add();
// 实例工厂
ApplicationContext context3 = new ClassPathXmlApplicationContext("beans.xml");
UserService userService3 = (UserService) context3.getBean("userService3");
userService3.add();}
}
感兴趣的可以自己看执行结果。三种结果都证明 bean 被 Spring 容器管理实例化了。
3、bean 的作用域 (掌握 singleton、prototype)
类别 | 说明 |
---|---|
singleton | 在 Spring IoC 容器中仅存在一个 Bean 实例,Bean 以单例方式存在,默认值 |
prototype | 每次从容器中调用 Bean 时,都返回一个新的实例,即每次调用 getBean() 时,相当于执行 new XxxBean() |
request | 每次 HTTP 请求都会创建一个新的 Bean,该作用域仅适用于 WebApplicationContext 环境 |
session | 同一个 HTTP Session 共享一个 Bean,不同 Session 使用不同 Bean,仅适用于 WebApplicationContext 环境 |
globalSession | 一般用于 Portlet 应用环境,该作用域仅适用于 WebApplicationContext 环境 |
案例代码演示
bean.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService1" class="com.example.demo.service.impl.UserServiceImpl" scope="prototype">
</bean>
</beans>
public class ServiceTest {public static void main(String[] args) {ApplicationContext context1 = new ClassPathXmlApplicationContext("beans.xml");
UserService userService1 = (UserService) context1.getBean("userService1");
UserService userService2 = (UserService) context1.getBean("userService1");
System.out.println(userService1);
System.out.println(userService2);
}
}
控制台信息如下:
com.example.demo.service.impl.UserServiceImpl@2a556333
com.example.demo.service.impl.UserServiceImpl@7d70d1b1
如果去掉 bean.xml 文件的 scope=”prototype”,打印信息如下:
com.example.demo.service.impl.UserServiceImpl@7a187f14
com.example.demo.service.impl.UserServiceImpl@7a187f14
所以 Spring IoC 容器 Bean 以单例方式默认存在!!配置的话根据自己需要配置单例或者多例