一、引言
1.1 原生web开发中存在哪些问题?
传统Web开发存在硬编码所造成的过度程序耦合(例如:Service中作为属性Dao对象)。
部分Java EE API较为复杂,使用效率低(例如:JDBC开发步骤)。
侵入性强,移植性差(例如:DAO实现的更换,从Connection到SqlSession)。
总结:代码的耦合度太高 操作数据库比较复杂 移植性差
1.2 解决方案
目标:
A.降低代码是耦合度 UserService 与UserDao紧密联系
B.把创建对象的主动权交给容器 由容器来创建对象以及管理对象
解决:
A.使用反射来创建对象
B.使用map容器来存储对象
C.使用配置文件来保存对象的信息 在运行期间编译修改
step01 新建配置文件
userDao=com.qf.dao.UserDaoImpl
userService=com.qf.service.impl.UserServiceImpl
step02 新建一个工厂类
package com.qf.utils;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class BeanFactory {
//用于加载配置文件
private static Properties properties;
//定义一个容器来管理对象
private static Map<String,Object> map;
static {
//实例化Properties 对象
properties = new Properties();
InputStream is = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
//加载配置文件
try {
properties.load(is);
//实例化Map集合
map = new HashMap<String, Object>();
//获取所有的key
Enumeration<Object> enume = properties.keys();
//使用循环遍历
while (enume.hasMoreElements()){
//获取key
String key = enume.nextElement().toString();
//获取value值
String value = properties.getProperty(key);
//通过反射来实例化对象
Class cla = Class.forName(value);
//创建对象
Object o = cla.newInstance();
//将对象存入容器中
map.put(key,o);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
//根据key获取值
public static Object getObject(String key){
return map.get(key);
}
}
step03 测试类
package com.qf.test;
import com.qf.service.UserService;
import com.qf.utils.BeanFactory;
public class Test {
public static void main(String[] args) {
//获取Userservice对象
// UserService userService = (UserService) BeanFactory.getObject("userService");
// // System.out.println(userService);
// userService.add();
for (int i=0;i<=5;i++){
UserService userService = (UserService) BeanFactory.getObject("userService");
System.out.println(userService);
}
}
}
二、Spring框架
2.1 概念
- Spring是一个项目管理框架,同时也是一套Java EE解决方案。
- Spring是众多优秀设计模式的组合(工厂、单例、代理、适配器、包装器、观察者、模板、策略)。
- Spring并未替代现有框架产品,而是将众多框架进行有机整合,简化企业级开发,俗称"胶水框架"。
- Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益
2.2 访问与下载
官方网站:https://spring.io/
三、Spring架构组成
Spring架构由诸多模块组成,可分类为
四、Spring Framework 体系
五 Spring 搭建
5.1 搭建
step01 导入依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.18</version>
</dependency>
</dependencies>
step02创建spring 配置文件 applicationConext.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="userService" class="com.qf.service.UserService"></bean>
</beans>
step03 测试类
package com.qf.test;
import com.qf.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test01 {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
Object userService = app.getBean("userService");
System.out.println(userService);
UserService userService1 = app.getBean("userService", UserService.class);
System.out.println(userService1);
UserService userService2 = app.getBean("userService", UserService.class);
System.out.println(userService2);
}
}
5.2 执行流程
六 Spring 控制反转(IOC)
6.1 控制反转
6.2 Bean的管理
6.2.1 使用默认的构造方法实例化对象
注意点:这种方式最常用 但是类中必须定义无参构造方法(特别是注解的时候)
6.2.2 使用工厂实例化
在很多情况下,对于第三方的代码或之前的老代码,很可能对象的创建是通过工厂来完成的。对于工厂创建出的对象交给spring容器管理。
step01 新建一个工厂类
package com.qf.utils;
import com.qf.entity.Student;
import com.qf.service.UserService;
public class BeanFactory {
Student stu(){
return new Student();
}
}
step02 新建spring 配置文件
<?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="beanFactory" class="com.qf.utils.BeanFactory" ></bean>
<!--需要工厂类创建对象 由 spring进行管理-->
<!--
factory-bean 找到spring容器创建这个对象的工厂
factory-method 创建对象的方法
-->
<bean id="student" factory-bean="beanFactory" factory-method="stu"></bean>
</beans>
step03 测试类
package com.qf.test;
import com.qf.entity.Student;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test02 {
public static void main(String[] args) {
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("bean01.xml");
Student s = app.getBean("student", Student.class);
System.out.println(s);
}
}
6.2.3 使用静态工厂实例化
ste01 新建一个静态工厂类
package com.qf.utils;
import com.qf.entity.Student;
public class StudentFactory {
public static Student getStudent(){
return new Student();
}
}
step02 修改配置文件
<?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="beanFactory" class="com.qf.utils.BeanFactory" ></bean>-->
<!--需要工厂类创建对象 由 spring进行管理-->
<!--
factory-bean 找到spring容器创建这个对象的工程
factory-method 创建对象的方法
-->
<!-- <bean id="student" factory-bean="beanFactory" factory-method="stu"></bean>-->
<bean id="stu" class="com.qf.utils.StudentFactory" factory-method="getStudent"></bean>
</beans>
step03 测试类
package com.qf.test;
import com.qf.entity.Student;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test02 {
public static void main(String[] args) {
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("bean01.xml");
Student s = app.getBean("stu", Student.class);
System.out.println(s);
}
}
6.2.4 bean的作用范围
业务层和持久层、表现层(Servlet、Filter等)对象一般使用单例对象。实体类一般使用多例对象。使用spring框架不用再自己编写单例模式了。默认情况下,交给spring容器管理的对象就是单例对象。
singleton:表示这个 bean 是单例的,默认即此。
- prototype:表示这个 bean 多多例的,每次从容器中获取 bean,都会拿到一个全新的 bean
下面这三个 scope ,在 web 环境下生效(将来我们学了 SpringMVC 之后,就可以使用这三个了)。 - request:在同一个请求中,拿到的始终是同一个对象。
- session:在同一个会话中,拿到的始终是同一个对象。
- application:在应用重启之前,拿到的始终是同一个对象。
代码-配置文件
<?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="actor" class="com.qf.entity.Actor"></bean>
</beans>
代码-测试类
package com.qf.test;
import com.qf.entity.Actor;
import com.qf.entity.Student;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test02 {
public static void main(String[] args) {
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("bean01.xml");
Actor a1= app.getBean("actor", Actor.class);
Actor a2= app.getBean("actor", Actor.class);
System.out.println(a1==a2);
}
}
6.2.5 bean生命周期中的两个特殊方法
初始化方法:是在构造方法执行后执行。
销毁方法:销毁对象之前执行。 (由jvm执行 由gc来进行垃圾回收)
step01 修改类
package com.qf.entity;
public class Actor {
public Actor(){
System.out.println("执行了构造方法......");
}
public void init(){
System.out.println("初始化");
}
public void destroy(){
System.out.println("销毁");
}
}
step02 配置文件
<?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="actor" class="com.qf.entity.Actor" scope="prototype"
init-method="init" destroy-method="destroy"></bean>
</beans>
七 spring依赖注入
7.1 依赖注入简介
1.依赖注入Dependency Injection 简称DI和IoC 是一回事。指原来自己创建对象,现在让别人传给你,就相当于注入进来。
2.依赖注入有两种方式 A.通过构造方法 B.通过set方法
7.2 依赖注入-构造方法
step01 新建User类
package com.qf.entity;
public class User {
private Integer uid;
private String uname;
public User() {
}
public User(Integer uid, String uname) {
this.uid = uid;
this.uname = uname;
}
}
step02 编写配置文件
<?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.qf.entity.User">
<!--通过构造方法注入值
name 表示属性名
value 表示属性值
-->
<constructor-arg name="uid" value="10"/>
<constructor-arg name="uname" value="张三"/>
</bean>
</beans>
step03 修改测试类
package com.qf.test;
import com.qf.entity.User;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test01 {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = applicationContext.getBean("user", User.class);
System.out.println(user);
}
}
7.3 依赖注入-set方法注入
step01 修改类 添加set get方法
step02 修改配置文件
<?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="u" class="com.qf.entity.User">
<property name="uid" value="12"></property>
<property name="uname" value="您好"></property>
</bean>
</beans>
7.4 依赖注入 -注入其它类型
step01 新建一个类
package com.qf.entity;
import java.util.*;
public class Person {
private Date bornDate;
private String[] hobbys;
private Set<String> phones;
private List<String> names;
private Map<String,String> countries;
private Properties files;
//注入自定义对象
private User user;
public Date getBornDate() {
return bornDate;
}
public void setBornDate(Date bornDate) {
this.bornDate = bornDate;
}
public String[] getHobbys() {
return hobbys;
}
public void setHobbys(String[] hobbys) {
this.hobbys = hobbys;
}
public Set<String> getPhones() {
return phones;
}
public void setPhones(Set<String> phones) {
this.phones = phones;
}
public List<String> getNames() {
return names;
}
public void setNames(List<String> names) {
this.names = names;
}
public Map<String, String> getCountries() {
return countries;
}
public void setCountries(Map<String, String> countries) {
this.countries = countries;
}
public Properties getFiles() {
return files;
}
public void setFiles(Properties files) {
this.files = files;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return "Person{" +
"bornDate=" + bornDate +
", hobbys=" + Arrays.toString(hobbys) +
", phones=" + phones +
", names=" + names +
", countries=" + countries +
", files=" + files +
", user=" + user +
'}';
}
}
step02 新建一个配置文件
<?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.qf.entity.User">
<property name="uid" value="11"></property>
<property name="uname" value="kkk"></property>
</bean>
<bean id="person" class="com.qf.entity.Person">
<property name="bornDate" value="2010/11/23"/>
<property name="hobbys">
<array>
<value>kkkkk</value>
<value>wwww</value>
</array>
</property>
<property name="phones">
<set>
<value>111111</value>
<value>222222</value>
</set>
</property>
<property name="names">
<list>
<value>3333333</value>
<value>4444444</value>
</list>
</property>
<property<