1.0 再次强调
IOC解耦只是削减计算机的耦合,但是不能消除,只能降低。
2.0 新建一个项目
填充基本的代码:
pom.xml
4.0.0
com.edp
second_project_spring
1.0-SNAPSHOT
jar
org.springframework
spring-context
5.2.3.RELEASE
bean.xml
AccountDaoImpl.java
package com.edp.dao.impl;
import com.edp.dao.IAccountDao;
/**
* @author EdPeng
* @Title:
* @Package
* @Description: 账户持久层实现类
* @date 2020/2/23下午 5:45
*/
public class AccountDaoImpl implements IAccountDao {
public void saveAccount() {
System.out.println("保存了账户。");
}
}
IAccountDao.java
package com.edp.dao.impl;
import com.edp.dao.IAccountDao;
public class AccountDaoImpl implements IAccountDao {
public void saveAccount() {
System.out.println("保存了账户。");
}
}
IAccountServiceImpl .java
package com.edp.service.impl;
import com.edp.dao.impl.AccountDaoImpl;
import com.edp.service.IAccountService;
import com.edp.dao.IAccountDao;
public class IAccountServiceImpl implements IAccountService {
public IAccountServiceImpl(){
System.out.println("IAccountServiceImpl对象创建了!");
}
public void saveAccount() {
System.out.println("IAccountService中的saveAccount方法执行了……");
}
}
IAccountService .java
package com.edp.service;
public interface IAccountService {
void saveAccount();
}
Client .java
package com.edp.ui;
import com.edp.service.IAccountService;
import com.edp.dao.IAccountDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Client {
public static void main(String[] args) {
//1.获取核心容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
//根据id获取bean对象
IAccountService accountService = (IAccountService) applicationContext.getBean("accountService");
System.out.println(accountService);
accountService.saveAccount();
}
}
3.0 spring对bean对象管理的细节——创建bean的三种方式
3.1 第一种方式:使用默认构造函数创建
在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时,采用的就是默认构造函数创造bean对象,此时如果类中没有默认构造函数,则对象无法创建。
比如我们修改IAccountServiceImpl .java
public class IAccountServiceImpl implements IAccountService {
public IAccountServiceImpl(String value){
System.out.println("IAccountServiceImpl对象创建了!");
}
public void saveAccount() {
System.out.println("IAccountService中的saveAccount方法执行了……");
}
}
将原来的默认构造函数修改为有参构造函数,意味着构造函数没有了,运行Client类:
而且,这样没有无参构造函数的情况下,bean.xml都在会编译环境下报错:
3.2 第二种方式:使用普通工厂中的方法创建对象(使用某个类中的方法创建,并存入spring容器)
这个方法解决加入需要配置的类在class字节码中(即集成的jar包中的类。)
创建一个模拟的工厂类
InstanceFactory.java
package com.edp.factory;
import com.edp.service.IAccountService;
import com.edp.service.impl.IAccountServiceImpl;
/**
* @author EdPeng
* @Title: 模拟一个工厂类
* @Package
* @Description:模拟工厂类(该类可能是存在于jar包中的,我们无法通过修改源码的方式来提供默认构造函数)
* @date 2020/2/29下午 5:46
*/
public class InstanceFactory {
public IAccountService getAccountService(){
return new IAccountServiceImpl();
}
}
这时候,bean.xml的配置如下:
运行:
成功运行,证明这样配置没有问题。
3.3 第三种方式:使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象,并存入spring容器)
新建一个StaticFactory.java类:
package com.edp.factory;
import com.edp.service.IAccountService;
import com.edp.service.impl.IAccountServiceImpl;
/**
* @author EdPeng
* @Title:模拟一个工厂类
* @Package
* @Description:模拟工厂类(该类可能是存在于jar包中的,我们无法通过修改源码的方式来提供默认构造函数)
* @date 2020/2/29下午 9:00
*/
public class StaticFactory {
public static IAccountService getAccountService() {
return new IAccountServiceImpl();
}
}
bean.xml配置也很简单:
运行:
注意,上面看上去两个Factory类其实已经耦合了,但是我们只是在模拟jar包中的类,jar包中有普通方法也有静态方法,spring都给我们提供配置的方法。
在jar包中的类都是“.class”文件,是无法改动的,当我们需要获得某个方法的返回值存入spring容器中,就需要用到以上3种中的第2、3种bean对象创建方法。
4.0 spring对bean对象管理的细节——bean对象的作用范围
4.1 spring的bean对象默认情况下就是单例的。
重置一下bean.xml:
修改Client.java类测试一下:
public class Client {
public static void main(String[] args) {
//1.获取核心容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
//根据id获取bean对象
IAccountService accountService = (IAccountService) applicationContext.getBean("accountService");
IAccountService accountService2 = (IAccountService) applicationContext.getBean("accountService");
System.out.println(accountService);
System.out.println(accountService2);
accountService.saveAccount();
accountService2.saveAccount();
System.out.println(accountService==accountService2);
}
}
执行:
4.2 bean标签的scope属性
修改bean.xml文件
执行:
其中
global-session:作用于集群环境的会话范围(全局会话范围),当不是集群环境时,它就是session
,一般情况下接触不到这个方面,但在此做以解释。
当我们用户访问服务器时,服务器往往都有一个访问地址,比如“192.168.0.1”,但在超大型项目中,一个服务器往往扛不住这么大的数据访问量,当在集群环境时,往往会有多个服务器ip地址供用户访问。
当我们访问一个大型网站,比如淘宝时,首先访问的是“https://www.taobao.com/”,用户打开的是一个login.jsp页面,然后网页就会寻找空闲的服务器ip地址提供数据服务。(专业名词叫“负载均衡”)
在用户注册账户时,将由一个空闲的服务器进行数据存储,但当用户登录的时候,服务器的情况已经瞬息万变,再次访问的时候,注册时的物理服务器已经不是现在登录的物理服务器,而这个时候,新的服务器不会存储用户的账户信息。
这时候就需要一个全局的集群环境的会话范围,能够让用户找到服务器所在信息的调度。这个会话模式在spring中的配置属性就是global-session。
5.0 spring对bean对象管理的细节——bean对象的生命周期
bean对象的生命周期
- 单例对象
- 出生:当容器创建时对象出生
- 活着:只要容器还在,对象一直活着
- 死亡:容器销毁,对象消亡
- 总结:单例对象的生命周期和容器相同
- 多例对象
- 出生:当我们使用对象时,spring框架为我们创建
- 活着:对象在使用过程中,一直活着
- 死亡:当对象长时间不用,且没有别的对象引用时,由java的垃圾回收器回收
6.0 Spring的依赖注入
6.1 什么是依赖注入(Dependency Injection)?
- IOC的作用:降低程序间的耦合(依赖关系),也就是降低程序间的依赖关系,而依赖关系的管理,以后都交给spring来维护。
- 在当前类需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中说明。
- 而针对这依赖关系的维护,就称之为依赖注入。
6.2 依赖注入分为三类
依赖注入能注入的数据分为三类:
- 基本类型和String
- 其他bean类型(在配置文件中或者注解配置过的bean)
- 复杂类型/集合类型
6.3 依赖注入的注入方式
总共有3种:
- 第1种:使用构造函数提供
- 第2种:使用set方法提供
- 第3种:使用注解提供
7.0 使用构造注入
首先在类中,定义一些可注入的变量。
修改IAccountServiceImpl.java
public class IAccountServiceImpl implements IAccountService {
//如果是经常变换的数据,并不适用于注入的方式
private String name;
private Integer age;
private Date birthday;
public IAccountServiceImpl(String name, Integer age, Date birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
public void saveAccount() {
System.out.println("IAccountService中的saveAccount方法执行了……"+name+" , "+age+" , "+birthday);
}
}
当然,我们不应该关注这些变量是不是应该出现在Dao层,只是说作为一个对象,以一种方便理解的方式命名。
配置bean.xml
运行:
发现,没有出现乱码,这就是Spring的强大之处:能把涉及到的可能的它能处理的细节都提前替我们处理。
8.0 set方法注入
注入只需要set方法,不需要get方法。
创建一个com.edp.service.impl.IAccountServiceImpl2 .java
public class IAccountServiceImpl2 implements IAccountService {
//如果是经常变换的数据,并不适用于注入的方式
private String name;
private Integer age;
private Date birthday;
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public void saveAccount() {
System.out.println("IAccountService中的saveAccount方法执行了……"+name+" , "+age+" , "+birthday);
}
}
配置bean.xml
修改Client.java
public class Client {
public static void main(String[] args) {
//1.获取核心容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
IAccountService accountService = (IAccountService) applicationContext.getBean("accountService2");
accountService.saveAccount();
}
}
执行:
set方法注入的优势就是就是构造函数注入的弊端,当然set方法注入的弊端就是构造函数注入的优势,但我们更常用的方式是set方法注入。
9.0 复杂类型的注入
创建com.edp.service.impl.IAccountServiceImpl3.java
package com.edp.service.impl;
import com.edp.service.IAccountService;
import java.util.*;
public class IAccountServiceImpl3 implements IAccountService {
private String[] myStr;
private List myList;
private Set mySet;
private Map myMap;
private Properties myProps;
public void setMyStr(String[] myStr) {
this.myStr = myStr;
}
public void setMyList(List myList) {
this.myList = myList;
}
public void setMySet(Set mySet) {
this.mySet = mySet;
}
public void setMyMap(Map myMap) {
this.myMap = myMap;
}
public void setMyProps(Properties myProps) {
this.myProps = myProps;
}
@Override
public String toString() {
return "IAccountServiceImpl3{" +
"\n myStr=" + Arrays.toString(myStr) +
",\n myList=" + myList +
",\n mySet=" + mySet +
",\n myMap=" + myMap +
",\n myProps=" + myProps +
'}';
}
public void saveAccount() {
System.out.println( toString());
}
}
修改bean.xml
AAA
BBB
CCC
修改Client.java
public class Client {
public static void main(String[] args) {
//1.获取核心容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
IAccountService accountService = (IAccountService) applicationContext.getBean("accountService3");
accountService.saveAccount();
}
}
执行:
继续完善bean.xml
AAA
BBB
CCC
DDD
EEE
FFF
GGG
HHH
III
执行:
接下来,我们如下操作,修改bean.xml:
AAA
BBB
CCC
DDD
EEE
FFF
GGG
HHH
III
执行:
将标签内的对应关系打乱,发现还是可以运行。
复杂类型(集合类型)的注入,用于给List结构集合注入的标签有:list、array、set;用于给map结构集合注入的标签有:map、props,结构相同的,标签可以互换。
10.0 使用注解注入
【Java中级】27.0 SSM之Spring框架(三)——注解注入
END