目录
一、spring概述
1.1、Spring是什么
1.2、 Spring体系编辑
二、 优质程序代码的书写原则
2.1、耦合与内聚
2.2、耦合和内聚代码示例
2.3、耦合的弊端:
2.4、如何实现解耦?
三、IOC的相关概念
四、 基于XML的IOC环境搭建
五、Spring中IOC容器(API)
5.1、bean工厂的结构
5.1.1 ApplicationContext: 应用上下文 接口 饿汉加载模式
5.1.2 BeanFactory: 懒汉式延迟加载
5.2、创建Bean对象的三种方式
5.2.1 通过工厂对象的方法来创建(静态及非静态)
5.3、Bean对象的作用范围
5.3.1 单例bean测试:
5.3.2 多例bean测试:
5.4、Bean对象的生命周期
六、Spring中的DI(依赖注入)
6.1、 IOC和DI区别
6.2、注入数据的方式和类型
6.2.1 有参构造注入
6.2.2 setter方式注入
6.2.3 setter注入其他bean类(User.class)
6.2.4 setter注入数组、集合、配置
七、扩展:单例延迟加载
一、spring概述
1.1、Spring是什么
Spring是分层的JavaSE/EE应用full-stack(全栈)轻量级开源框架;
①Spring框架是J2EE企业级应用的轻量级开源框架,提供了表现层springmvc和持久springJDBC(JDBCTemplate),以及业务层的事务管理等企业级应用解决方案;
②Spring还能将开源世界中众多优秀的第三方框架进行集成(比如mybatis等),成为了越来越受欢迎的J2EE企业级应用框架;
③Spring是以IOC(Inversion Of Control)控制反转和AOP(Aspect Oriented Programming)面向切面编程为核心;
1.2、 Spring体系
源码下载地址: https://repo.springsource.org/libs-release-local/org/springframework/spring/
二、 优质程序代码的书写原则
2.1、耦合与内聚
- 耦合(Coupling):代码书写过程中所使用技术的结合紧密度(程序之间的依赖程度),用于衡量软件中各个模块之间的互联程度
- 内聚(Cohesion):代码书写过程中单个模块内部各组成部分间的联系,用于衡量软件中各个功能模块内部的功能联系
- 程序书写的目标:高内聚,低耦合
- 就是同一个模块内的各个元素之间要高度紧密,但是各个模块之间的相互依存度却不要那么紧密
2.2、耦合和内聚代码示例
//耦合:程序代码之间的依赖关系
public class UserService(){
public List<User> getAllUser(){
/**
* getAllUser方法的执行需要依赖UserDao类,
* 我们称,getAllUser方法与UserDao类之间有耦合
**/
UserDao userDao=new UserDao();
return userDao.findAll();
}
}
public class UserDao(){
public List<User> findAll(){
//do something and return list
}
}
//内聚:一个方法只做一件事情(一个类只聚合一个业务属性集)
//反例: 此方法不符合高内聚思想
public int compute(int i,int j,String label){
if("+".equals(label)){
return i+j;
}else if("-".equals(label)){
return i-j;
}else{
//do something....
}
}
//例子:
public int add(int i,int j){
return i+j;
}
public int sub(int i,int j){
return i-j;
}
//......
思考:以下代码存在哪些耦合问题?
public class Demo {
public static void findAll() throws Exception {
// jdbc操作数据库
//1.注册驱动: 将mysql提供的驱动类加载到内存中,并交个DriverManager管理
DriverManager.registerDriver(new Driver()); // 注册了2次,且存在耦合
//Class.forName("com.mysql.jdbc.Driver"); // 反射方式,注册驱动
// 将驱动的全限定名设置到配置文件中,通过读取配置文件,获取实现类的全限定名,从而实现解耦.
// 实现解耦后,当修改驱动时,无需修改任何java代码,只需要修改配置文件即可
//2.获取连接
String url = "jdbc:mysql://localhost:3306/spring_116";
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, username, password);
//3.编写sql语句
String sql = "select * from account ";
//4.获取语句执行者
PreparedStatement pst = conn.prepareStatement(sql);
//5.执行sql并返回结果集
ResultSet rs = pst.executeQuery();
//6.处理结果集
while (rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
float money = rs.getFloat("money");
System.out.println(id+ " : "+name+" : "+money);
}
//7.关闭连接
rs.close();
pst.close();
conn.close();
}
}
说明:
- 耦合: 程序代码之间的依赖关系
- 低耦合: 降低程序代码之间的依赖关系,从而方便维护扩展和重用
- 解耦合: 在java程序代码中,耦合是不可能完全解开的,我们所说的"解耦合"指的是解开程序编译期的耦合
2.3、耦合的弊端:
独立性差 可重用性不高 维护成本高
2.4、如何实现解耦?
①原始方案:服务层与持久层存在紧耦合;
②加入工厂模式后,服务层与持久层完成解耦,但是工厂类与持久层存在紧耦合;
③通过工厂模式和静态资源配置将代码的耦合降到最低;
最终方案:工厂+配置文件解耦
bean多实例-工厂类代码
/**
* bean工厂: 专门用于创建Bean对象(java对象)
*/
public class BeanFactory {
// 用于存放解析到的全限定名
private static Map<String,String> urlMap = new HashMap<>();
static {
// 1.解析配置文件,获取配置文件中配置的全限定名
// ResourceBundle: jdk提供的工具,专门用于解析properties配置文件
ResourceBundle bundle = ResourceBundle.getBundle("beans");
// 获取properties配置文件中所有的key
Enumeration<String> keys = bundle.getKeys();
while (keys.hasMoreElements()){
// 获取下一个key
String key = keys.nextElement();
// 根据key获取对应的全限定名
String value = bundle.getString(key);
// 存放到map集合中
urlMap.put(key,value);
}
// 测试是否解析到了数据
for (String key:urlMap.keySet()){
System.out.println(key+" : "+urlMap.get(key));
}
}
// 反射创建类对象
public static Object getBean(String id) {
try {
// 根据id获取对应的类的全限定名
String className = urlMap.get(id);
// 反射创建类对象
Object obj = Class.forName(className).newInstance();
return obj;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
bean单实例-工厂代码
/**
* bean工厂: 专门用于创建Bean对象(java对象)
*/
public class BeanFactory1 {
// 用于存放创建的bean对象(容器)
private static Map<String,Object> beansMap = new HashMap<>();
// 用于存放解析到的全限定名
private static Map<String,String> urlMap = new HashMap<>();
static {
// 1.解析配置文件,获取配置文件中配置的全限定名
// ResourceBundle: jdk提供的工具,专门用于解析properties配置文件
ResourceBundle bundle = ResourceBundle.getBundle("beans");
// 获取properties配置文件中所有的key
Enumeration<String> keys = bundle.getKeys();
while (keys.hasMoreElements()){
// 获取下一个key
String key = keys.nextElement();
// 根据key获取对应的全限定名
String value = bundle.getString(key);
// 存放到map集合中
urlMap.put(key,value);
}
// 测试是否解析到了数据
for (String key:urlMap.keySet()){
System.out.println(key+" : "+urlMap.get(key));
}
}
// 反射创建类对象
public static Object getBean(String id) {
try {
// 先从bean容器中获取对象
Object obj = beansMap.get(id);
if(obj==null){
// 根据id获取对应的类的全限定名
String className = urlMap.get(id);
// 反射创建类对象
obj = Class.forName(className).newInstance();
// 将创建好的bean对象存放到beansMap容器中
beansMap.put(id,obj);
}
return obj;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
立即加载的方式创建
/**
* bean工厂: 专门用于创建Bean对象(java对象)
*/
public class BeanFactory2 {
// 用于存放创建的bean对象(容器)
private static Map<String,Object> beansMap = new HashMap<>();
// 用于存放解析到的全限定名
private static Map<String,String> urlMap = new HashMap<>();
static {
try {
// 1.解析配置文件,获取配置文件中配置的全限定名
// ResourceBundle: jdk提供的工具,专门用于解析properties配置文件
ResourceBundle bundle = ResourceBundle.getBundle("beans");
// 获取properties配置文件中所有的key
Enumeration<String> keys = bundle.getKeys();
while (keys.hasMoreElements()){
// 获取下一个key
String key = keys.nextElement();
// 根据key获取对应的全限定名
String value = bundle.getString(key);
// 存放到map集合中
urlMap.put(key,value);
// 立即加载的思想创建bean对象
Object obj = Class.forName(value).newInstance();
// 将创建好的对象存放到beansMap容器中
beansMap.put(key,obj);
}
// 测试是否解析到了数据
// for (String key:urlMap.keySet()){
// System.out.println(key+" : "+urlMap.get(key));
// }
} catch (Exception e) {
e.printStackTrace();
}
}
// 反射创建类对象
public static Object getBean(String id) {
try {
// 先从bean容器中获取对象
Object obj = beansMap.get(id);
if(obj==null){
// 根据id获取对应的类的全限定名
String className = urlMap.get(id);
// 反射创建类对象
obj = Class.forName(className).newInstance();
// 将创建好的bean对象存放到beansMap容器中
beansMap.put(id,obj);
}
return obj;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
配置文件
# 格式:key=value
# key: 自定义,一般为当前类实现的接口的名称
# value: 当前需要使用的类的全限定名
userDao=com.hhy.dao.impl.UserDaoImpl
userService=com.hhy.service.UserServiceImpl
三、IOC的相关概念
- IoC(Inversion Of Control)控制反转,Spring反向控制应用程序所需要使用的外部资源;
- Spring控制的资源全部放置在Spring容器中,该容器称为IoC容器;
- spring容器中存储的对象称为bean对象;
IOC(inversion of control): 控制反转,反转的是对象的创建权,用于削减程序之间的耦合关系,底层使用反射技术实现
传统方式创建对象: new 对象(); (主动创建)
IOC方式创建对象: 找容器(被动接收),本质上就是一个Map集合作用:解耦
通过标记(标记就是配置文件中的key)找工厂,工厂帮我们创建对应的类对象,并返回给我们使用
当前类可以选择主动出击(new的方式)创建对象,但是此时耦合度高。
把主动式改成被动接收,由工厂对象为当前类生产所必须的关联对象,此时降低了两个类的依赖关系。
四、 基于XML的IOC环境搭建
准备接口及实现类:
public interface AccountService {
void add();
void init();
void destroy();
}
public class AccountServiceImpl implements AccountService {
//用于判断何时被创建
public AccountServiceImpl() {
System.out.println("AccountServiceImpl构造器被调用");
}
@Override
public void add() {
System.out.println("add被调用");
}
@Override
public void init() {
//测试bean的生命周期
System.out.println("AccountServiceImpl初始化");
}
@Override
public void destroy() {
//测试bean的生命周期
System.out.println("AccountServiceImpl销毁");
}
}
1.导入Spring的核心jar包的坐标:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
</dependencies>
2.创建applicationContext.xml,并导入约束:
id: 容器中的唯一标识 class:被创建的类的全限定名(包名+类名)
<?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">
<!-- 方式一: 无参构造创建对象,存放到IOC容器中 -->
<!-- id: 容器中的唯一标识 class:被创建的类的全限定名(包名+类名) -->
<bean id="accountService" class="hhy.service.impl.AccountServiceImpl"></bean>
</beans>
xml和properties区别:
二者都可以做配置文件
properties更容易解析
Spring之所以使用xml作为配置文件,是因为:
xml结构清晰,嵌套关系明确,一目了然
xml可以通过嵌套关系描述更多的事情.
测试:
@Test
public void t1() {
// ClassPathXmlApplicationContext: 读取类路径下的xml文件
// 类路径: 指的就是resources目录
//1.调用Spring的API,解析配置文件让Spring创建IOC容器
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
//2.调用应用上下文对象的API,从IOC容器中获取类对象
//AccountService service = (AccountService) ac.getBean("AccountService");
//传入对应类,不用强转
AccountService service = ac.getBean("accountService", AccountService.class);
service.add();
}
五、Spring中IOC容器(API)
5.1、bean工厂的结构
5.1.1 ApplicationContext: 应用上下文 接口 饿汉加载模式
ApplicationContext: 当解析完applicationContext.xml文件后,立即创建类对象(饿汉加载模式)
它是一个接口。是spring中的IOC容器接口,可以通过该接口的方法来获取想要的bean对象。需要提供bean的id。
它有3个常用的实现类
ClassPathXmlApplicationContext★:
它是用于读取类路径(resources)下的xml配置文件,不在类路径下读取不到
FileSystemXmlApplicationContext:
它是读取文件系统中的配置文件,只要有访问权限,在文件系统中都能读取的到
AnnotationConfigApplicationContext:
它是用于根据注解配置 创建容器的。
(★★)ApplicationContext它是在一读取完配置文件,就马上创建配置文件中所配置的所有对象。(得到IOC容器)
在IDEA中查看类的继承体系:
ctrl + alt + U
ApplicationContext: 饿汉加载模式
5.1.2 BeanFactory: 懒汉式延迟加载
BeanFactory:
它是spring中ioc容器的顶层接口,ApplicationContext只是它的子接口。
它提供创建容器中对象的时机,使用延迟加载(懒加载)的思想。而ApplicationContext不仅继承了它的加载方式,而且还扩展出来了立即加载思想的创建容器的方式。
它是每次在使用时才真正的创建对象。
//使用beanFactory加载 懒汉式延迟加载
@Test
public void t2() {
ClassPathResource resource = new ClassPathResource("applicationContext.xml");
XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(resource);
//如注释其他代码 则对象不会被创建
AccountService accountService = xmlBeanFactory.getBean("accountService", AccountService.class);
accountService.add();
}
5.2、创建Bean对象的三种方式
第一种:通过默认构造函数创建(上面用的就是)
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl"></bean>
此种方式通常用于我们自己写的类,在spring中配置。
第二种:通过工厂对象的方法来创建(静态)
class属性: 指定的是工厂的全限定类名
factory-method属性:指定的是工厂中用于创建对象的静态方法
<bean id="userService" class="com.itheima.factory.StaticFactory" factory-method="createBean"></bean>
此种方法通常用于不是我们自己写的类,而是存在于jar包中已经写好的类。(它都是.class文件)
第三种:通过工厂对象的方法来创建(非静态)
factory-bean属性:指定的是工厂bean的id.
factory-method属性:指定的是工厂中用于创建对象的非静态方法
<bean id="instanceFactory" class="com.itheima.factory.InstanceFactory"></bean>
<bean id="userService" factory-bean="instanceFactory" factory-method="createBean"></bean>
此种方式通常用于不是我们自己写的类。
5.2.1 通过工厂对象的方法来创建(静态及非静态)
准备:
public class serviceFactory {
//该静态方法方法被调用时 创建一个对象 交给springIOC管理
public static AccountService getInstance() {
return new AccountServiceImpl();
}
//该非静态方法被调用时 创建一个对象 交给springIOC管理
public AccountService getInstance2() {
return new AccountServiceImpl();
}
}
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">
<!--
将项目中一切可能使用到的对象通通创建出来,并交个Spring的IOC管理
创建Bean对象的三种方式
方式1: 无参构造创建对象,存放到IOC容器中
方式2: 调用工厂的静态方法创建类对象,存放到IOC容器中
方式3: 调用工厂的非静态方法创建类对象,存放到IOC容器中
-->
<!-- 方式1: 无参构造创建对象,存放到IOC容器中 -->
<!-- id: 容器中的唯一标识 class:被创建的类的全限定名(包名+类名) -->
<bean id="accountService" class="hhy.service.impl.AccountServiceImpl"></bean>
<!-- 方式2: 调用工厂的静态方法创建类对象,存放到IOC容器中 -->
<!--
调用工厂的静态方法,将方法的返回值存放到IOC容器中
id: 存放到IOC容器时,对象的唯一标识
class: 工厂的全限定名
factory-method: 指定静态方法名称 getInstance表示当前类同该方法获取bean并加入springIOC容器
-->
<bean id="staticFactory" class="hhy.factory.serviceFactory" factory-method="getInstance"></bean>
<!-- 方式3: 调用工厂的非静态方法创建类对象,存放到IOC容器中 -->
<!--3.1: 创建工厂类对象,并存放到IOC容器中 -->
<bean id="serviceFactory" class="hhy.factory.serviceFactory"></bean>
<!--3.2: 调用工厂实例的非静态方法创建类对象 -->
<!--
调用工厂的非静态方法,将非静态方法的返回值存放到IOC容器中
id:存放到IOC容器时,对象的唯一标识
factory-bean:工厂对象实例的引用
factory-method:调用实例工厂的非静态方法
-->
<bean id="noStaticFactory" factory-bean="serviceFactory" factory-method="getInstance2"></bean>
</beans>
测试:
//通过工厂对象的方法来创建(静态及非静态)
@Test
public void t3() {
// ClassPathXmlApplicationContext: 读取类路径下的xml文件 类路径: 指的就是resources目录
//1.调用Spring的API,解析配置文件让Spring创建IOC容器
//饿汉模式 (测试:如注释其他代码只读取xml文件,能立即创建对象)
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
//2.调用应用上下文对象的API,从IOC容器中获取类对象 传入对应类,不用强转
//静态
AccountService service = ac.getBean("staticFactory", AccountService.class);
service.add();
//非静态
AccountService service2 = ac.getBean("noStaticFactory", AccountService.class);
service2.add();
}
5.3、Bean对象的作用范围
bean的作用范围调整:
调整bean的作用范围,使用的是bean标签的scope属性。
它的属性取值有以下5个
singleton :单例对象(只存在一个) 用的最多的 它是默认值(最常用)
prototype :多例对象(调一次生成一个) 用的最多的
------------------------------------
request :请求范围 (存入了请求域)
session :会话范围 (存入了会话域)
global-session :全局会话范围 当非集群环境下,它就是session
5.3.1 单例bean测试:
xml
<!-- 测试IOC容器中bean的作用范围
scope: 域,范围
singleton : 默认值,单实例对象
prototype : 多实例对象
-->
<!--配置单例bean-->
<bean id="accountService" scope="singleton" class="hhy.service.impl.AccountServiceImpl"></bean>
<!--配置多例bean-->
<bean id="accountService2" scope="prototype" class="hhy.service.impl.AccountServiceImpl2"></bean>
//测试单例
@Test
public void t4() {
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService service1 = ac.getBean("accountService", AccountService.class);
System.out.println("service1 = " + service1);
AccountService service2 = ac.getBean("accountService", AccountService.class);
System.out.println("service2 = " + service2);
System.out.println(service1==service2);
//true
}
5.3.2 多例bean测试:
@Test
public void t5() {
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService service1 = ac.getBean("accountService2", AccountService.class);
System.out.println("service1 = " + service1);
AccountService service2 = ac.getBean("accountService2", AccountService.class);
System.out.println("service2 = " + service2);
System.out.println(service1==service2);
//false
}
5.4、Bean对象的生命周期
bean对象的生命周期: 从加载到内存哪一刻起对象就出生了,当对象从内存中移除时,对象的生命就完结了
bean的生命周期:
单例对象: 将创建的bean放入容器
出生:容器创建,对象出生
活着:只要容器在,对象就一直活着
死亡:容器销毁,对象消亡
特点: 生命周期与容器相同
<!-- 测试IOC容器中bean的生命周期:
单实例:
创建: 配置文件解析完毕后,会立即创建对象,并存放到IOC容器中
销毁: IOC容器销毁销毁
多实例:
创建: 调用getBean方法时创建.
销毁: 等待GC回收
-->
<!--
init-method: 初始化方法(构造器初始化对象之后被调用)
destroy-method: 销毁时调用的方法(对象被销毁之前被调用)
-->
<!--为避免影响 二至注释掉其一-->
<!--单例bean的生命周期-->
<!-- <bean id="accountService3" class="hhy.service.impl.AccountServiceImpl"-->
<!-- init-method="init" destroy-method="destroy"></bean>-->
<!--多例bean的生命周期 prototype-->
<bean id="accountService4" class="hhy.service.impl.AccountServiceImpl"
scope="prototype"
init-method="init" destroy-method="destroy"></bean>
多例对象:
出生:每次使用时创建
活着:在使用过程中
死亡:使用完成之后,等待垃圾回收器回收。
多实例bean对象的生命周期
scope的值必须为: prototype
//单例生命周期 初始化一次、销毁一次
@Test
public void 测试单例bean生命周期() {
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
//调用两次 只init一次
AccountService service1 = ac.getBean("accountService3", AccountService.class);
AccountService service2 = ac.getBean("accountService3", AccountService.class);
ClassPathXmlApplicationContext cl= (ClassPathXmlApplicationContext) ac;
cl.close();
}
//多例生命周期 创建几个对象就初始化几次、等待垃圾回收销毁
@Test
public void 测试多例bean生命周期() {
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
//调用两次 只init一次
AccountService service1 = ac.getBean("accountService4", AccountService.class);
AccountService service2 = ac.getBean("accountService4", AccountService.class);
ClassPathXmlApplicationContext cl= (ClassPathXmlApplicationContext) ac;
cl.close();
}
六、Spring中的DI(依赖注入)
介绍:
依赖注入:Dependency Injection
通俗来讲: 缺什么给什么(给的对象从IOC容器中获取)
简单的说,就是在程序运行期,给当前类传入依赖的对象。缺什么传什么。
例如:
在创建UserService的bean对象时,该对象中需要依赖UserDao对象,那么就将这些依赖的对象注入当前对象中;
6.1、 IOC和DI区别
- IoC与DI是同一件事站在不同角度看待问题
在应用程序的角度看程序需要被动等待Spring提供资源(注入资源)是DI;
但是在Spring容器的角度看是,是将资源的创建权利做了翻转,且由容器提供数据,是IOC; - 如半杯水,看待角度不同则想法不同。
半杯水:乐观的人会庆幸还有半杯水,而悲观的人是恼怒只5有半杯水;
6.2、注入数据的方式和类型
Spring中的依赖注入:
注入的方式有三种:
第一种:使用构造方法注入
要求:必须有对应参数列表的构造函数
第二种:使用set方法注入(XML开发主流)
要求:提供被注入对象的set方法(不需要get方法)
第三种:使用注解注入(第二天会学)
注入的数据类型有三类:
第一类:基本类型和String
第二类:其他bean类型
要求:其他bean指的是在spring的配置文件中定义过的bean,或者是用注解注释过的类。
第三类:复杂类型(集合类型)
Array: 数组
List:
Map:
Properties:
数据准备:
@Data
public class DataSourceInfo {
private String driverClass;
private String url;
private String userName;
private String password;
private int port;
private User user;
private String[] strArr;
private List<String> list;
private Map<String,String> map;
private Properties properties;
public DataSourceInfo() {
}
//用于xml中有参构造注入
public DataSourceInfo(String driverClass, String url, String userName, String password) {
this.driverClass = driverClass;
this.url = url;
this.userName = userName;
this.password = password;
}
}
6.2.1 有参构造注入
配置xml时,类有参构造对应xml中name;
<!-- 方式1: 有参构造 -->
<bean id="dataSourceInfo" class="hhy.pojo.DataSourceInfo">
<constructor-arg name="driverClass" value="com.mysql.jdbc.Driver"></constructor-arg>
<constructor-arg name="userName" value="root"></constructor-arg>
<constructor-arg name="password" value="123456"></constructor-arg>
<constructor-arg name="url" value="jdbc:mysql:///test0908"></constructor-arg>
</bean>
//DI注入:有参构造
@Test
public void t1() {
// ClassPathXmlApplicationContext: 读取类路径下的xml文件 类路径: 指的就是resources目录
//饿汉模式 如注释其他代码只读取xml文件,立即创建对象
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext2.xml");
//2.调用应用上下文对象的API,从IOC容器中获取类对象
//AccountService service = (AccountService) ac.getBean("AccountService");
//传入对应类,不用强转
DataSourceInfo service = ac.getBean("dataSourceInfo", DataSourceInfo.class);
System.out.println("有参构造 = " + service);
}
6.2.2 setter方式注入
<!-- 方式2: 通过setter方法注入 -->
<bean id="setterData" class="hhy.pojo.DataSourceInfo">
<property name="userName" value="迪迦"></property>
<property name="password" value="666"></property>
<property name="url" value="www.dijia.com"></property>
</bean>
@Test
public void setter注入() {
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext2.xml");
//2.调用应用上下文对象的API,从IOC容器中获取类对象
//AccountService service = (AccountService) ac.getBean("AccountService");
//传入对应类,不用强转
DataSourceInfo service = ac.getBean("setterData", DataSourceInfo.class);
System.out.println("setter注入 = " + service);
}
6.2.3 setter注入其他bean类(User.class)
<bean id="classData" class="hhy.pojo.DataSourceInfo">
<!-- 注入其他bean类型 name中user为DataSourceInfo类成员,ref中userb对应下面User类属性-->
<property name="user" ref="userb"></property>
</bean>
<!-- 创建user对象存放到IOC容器中 -->
<bean id="userb" class="hhy.pojo.User">
<property name="name" value="大幂幂"></property>
<property name="age" value="18"></property>
</bean>
@Test
public void 实体类注入() {
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext2.xml");
//2.调用应用上下文对象的API,从IOC容器中获取类对象
//AccountService service = (AccountService) ac.getBean("AccountService");
//传入对应类,不用强转
DataSourceInfo service = ac.getBean("classData", DataSourceInfo.class);
System.out.println("实体类注入 = " + service);
}
6.2.4 setter注入数组、集合、配置
<bean id="moreData" class="hhy.pojo.DataSourceInfo">
<!-- 注入数组 -->
<property name="strArr">
<array>
<value>宝强</value>
<value>乃亮</value>
<value>羽凡</value>
<value>大郎</value>
</array>
</property>
<!-- 注入list -->
<property name="list">
<list>
<value>蓉蓉</value>
<value>璐璐</value>
<value>合合</value>
<value>莲莲</value>
</list>
</property>
<!-- 注入map-->
<property name="map">
<map>
<entry key="name" value="波波"></entry>
<entry key="age" value="18"></entry>
<entry key="sex" value="妖"></entry>
</map>
</property>
<!-- 注入properties -->
<property name="properties">
<props>
<prop key="name">迪迦</prop>
<prop key="age">18</prop>
</props>
</property>
</bean>
@Test
public void 数组集合配置注入() {
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext2.xml");
//2.调用应用上下文对象的API,从IOC容器中获取类对象
//AccountService service = (AccountService) ac.getBean("AccountService");
//传入对应类,不用强转
DataSourceInfo service = ac.getBean("moreData", DataSourceInfo.class);
System.out.println("数组集合注入 = " + service);
}
七、扩展:单例延迟加载
使用lazy-init="true"
<bean id="test" lazy-init="true" class="hhy.pojo.Test">