web项目,面向接口编程
以前:
public class HelleServlet extends HttpServlet{
UserService service = new UsrServiceImpl();
void doGet(){
service.findUser();
}
}
public interface UserService{
User findUser();
}
public class UserServiceImpl implements UserService {
User findUser() {
// ...
}
}
获取对象有缺点:
1 UserServlet类还是需要和UserService和UserServiceImpl耦合
2 扩展性不好,假如有新的实现类UserServiceImpl2,就需要改动代码
现在需要一种技术,降低耦合且还可以根据运行时状态给属性动态赋值,让方法体现多态性
----->>>Spring框架
Spring
官网: Spring | Home [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-870VaOy0-1663932882575)(D:/%E5%8D%83%E5%B3%B0%E4%B8%8A%E8%AF%BE/Every%20Day%20Stage3/day55/code/day55_spring.assets/image-20220923094840679.png)]
Spring框架是一个开放源代码的J2EE应用程序框架,由[Rod Johnson](https://baike.baidu.com/item/Rod Johnson/1423612)发起,是针对bean的生命周期进行管理的轻量级容器(lightweight container)。 Spring解决了开发者在J2EE开发中遇到的许多常见的问题,提供了功能强大IOC、AOP及Web MVC等功能。Spring可以单独应用于构筑应用程序,也可以和Struts、Webwork、Tapestry等众多Web框架组合使用,并且可以与 Swing等桌面应用程序AP组合。因此, Spring不仅仅能应用于J2EE应用程序之中,也可以应用于桌面应用程序以及小应用程序之中。Spring框架主要由七部分组成,分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC。
总结:
1 Spring开源,轻量级J2EE框架
2 主要功能:IOC(控制反转),AOP(面向切面)
3 本身是一种容器技术,可以方便整合其他框架
架构图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9XnOg7b0-1663932882576)(day55_spring.assets/image-20220923095759549.png)]
搭建Spring的环境
1 创建maben-java项目
2 导入依赖:
<dependencies>
<!--spring-context依赖中关联了其他核心依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
</dependencies>
spring的配置文件
-
位置:resources
-
格式:xml
-
名称:一般叫做applicationContext.xml beans.xml spring-context.xml app.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"> </beans>
DI-依赖注入(属性赋值)
依赖注入其实就是属性赋值.
演示: 给UserServiceImpl类中的UserDao属性赋值
public class UserServiceImpl implements UserService {
// 创建Dao对象
private UserDao userDao;
// 给属性提供set方法
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void findUserById() {
System.out.println("UserServiceImpl.findUserById()执行" );
userDao.findUserById();
}
}
public interface UserDao {
void findUserById();
}
public class UserDaoImpl implements UserDao {
@Override
public void findUserById() {
System.out.println("UserDaoImpl.findUserById");
}
}
<bean id="userService" class="com.qf.service.impl.UserServiceImpl">
<!-- 给属性赋值(DI)
1) 属性要有set方法
2) 属性值是另一个类对象,所以需要使用ref引用另一个类的对象id
-->
<property name="userDao" ref="userDao"></property>
</bean>
<!-- 创建一个UserDao对象 -->
<bean id="userDao" class="com.qf.dao.impl.UserDaoImpl"/>
@Test
public void test(){
String path = "applicationContext.xml";
// 根据配置文件创建出spring容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(path);
// 从容器中取出对象(根据对象名获得对象)
UserService userService = (UserService) context.getBean("userService");
userService.findUserById();
}
依赖注入
依赖注入就是给属性赋值,Spring提供了两种方案,一种set方式赋值,另一种是构造方法赋值
Set方式[熟悉]
依赖注入-基本类型
public class User {
private int id;
private String username;
private Date birthday;
private double score;
// set get...
}
<bean id="user" class="com.qf.model.User">
<!--
一个property标签给一个属性赋值
name 是类的属性名 value是属性值
-->
<property name="id" value="18"/>
<property name="username" value="admin"/>
<property name="score" value="99.9"/>
<!-- 日期这里使用value赋值,且格式只能是yyyy/MM/dd格式 -->
<property name="birthday" value="2000/01/01"/>
</bean>
@Test
public void test2(){
String path = "applicationContext.xml";
// 根据配置文件创建出spring容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(path);
// 从容器中取出对象(根据对象名获得对象)
User user = (User) context.getBean("user");
System.out.println(user );
}
依赖注入-容器(数组,List,Set,Map)
public class User{
// 容器类型
private String[] phones;
private List<String> list;
private Set<String> set;
private Map<String,Integer> map;
// set get
}
<bean id="user" class="com.qf.model.User">
<!-- 数组 -->
<property name="phones">
<array>
<value>110</value>
<value>120</value>
<value>119</value>
</array>
</property>
<!-- List,会允许重复 -->
<property name="list">
<list>
<value>奔驰</value>
<value>奔驰</value>
<value>宝马</value>
<value>奥迪</value>
</list>
</property>
<property name="set">
<!-- Set,不允许重复 -->
<set>
<value>145平</value>
<value>145平</value>
<value>155平</value>
<value>165平</value>
</set>
</property>
<!--Map-->
<property name="map">
<map>
<entry key="一" value="1"/>
<entry key="二" value="2"/>
<entry key="三" value="3"/>
</map>
</property>
</bean>
@Test
public void test2(){
String path = "applicationContext.xml";
// 根据配置文件创建出spring容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(path);
// 从容器中取出对象(根据对象名获得对象)
User user = (User) context.getBean("user");
System.out.println(user );
}
依赖注入-注入自定义类属性
public class Address {
private String country;
private String province;
private String city;
// set get
}
public class User {
// 对象属性
private Address address;
// set get
}
<!-- Address对象 -->
<bean id="address" class="com.qf.model.Address">
<property name="country" value="中国"/>
<property name="province" value="河南"/>
<property name="city" value="郑州"/>
</bean>
<!-- User对象 -->
<bean id="user" class="com.qf.model.User">
<property name="address" ref="address"/>
</bean>
构造方法注入[了解]
public class Student {
private int age;
private String name;
// 不用提供set get方法
public Student(){}
// 提供有参构造
public Student(int age){
this.age = age;
}
public Student(String name){
this.name = name;
}
public Student(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
<!-- Studnet对象 -->
<bean id="student" class="com.qf.model.Student">
<!-- 一个constructor-arg对应类中一个构造方法参数
name是构造方法中的参数名,value参数赋值
-->
<constructor-arg name="age" value="18"/>
<constructor-arg name="name" value="杉杉"/>
</bean>
@Test
public void test3(){
String path = "applicationContext.xml";
// 根据配置文件创建出spring容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(path);
// 从容器中取出对象(根据对象名获得对象)
Student stu = (Student) context.getBean("student");
System.out.println(stu );
}
自动注入[了解其注入方式]
需求: 给UserServiceImpl类中的UserDao属性赋值
<!--
autowire 属性,spring会在自动给UseServiceImpl类中的属性赋值
自动注入的方式:
byName: 通过名字注入
是属性名跟当前容器中bean标签id一致,既可以自动注入
byTyoe: 通过类型注入
需要给中属性赋值,会在当前容器根据类型找到后,自动赋值
与对象名无关.如果当前容器中有多个该类型的值,会赋值失败
-->
<bean id="userService" class="com.qf.service.impl.UserServiceImpl" autowire="byType"/>
<bean id="userDao1" class="com.qf.dao.impl.UserDaoImpl"/>
总结: 掌握
自动注入的两种方式:
byName: 通过属性名和容器中对象名一致,即可自动注入
byType: 属性类型和容器中对象的类型一致,即可自动注入
注解实现IOC-DI[重点|掌握]
目前我们都是使用xml配置实现IOC和DI,以后可以使用注解实现IOC和DI,即XML中不再配置很多标签了.
常用注解
注解 | 作用 | 被替代标签 | 位置 |
---|---|---|---|
@Component | 创建对象 | 类上 | |
@Controller | 创建对象 | 控制层的类上 | |
@Service | 创建对象 | 业务层的类上 | |
@Repository | 创建对象 | 持久层的类上 | |
@Value | 给基本类型属性赋值 | 属性上 | |
@Autowired | 给引用类型属性赋值 | autowired的属性 | 属性上 |
@Component,@Controller,@Service,@Repository都是用来创建对象,只不过建议是在相应的位置使用相应的注解
演示1:
需求: Teacher类,使用注解来创建Teacher类对象,以及给对象属性赋值
package com.qf.model;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* --- 天道酬勤 ---
*
* @author QiuShiju
* @desc
*/
@Component // 取代<bean>,默认对象名就是类名小写
public class Teacher {
@Value("20") // 取代<property>
private int age;
@Value("老王")
private String name;
@Value("2020/01/01")
private Date birthday;
// set get toString
}
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--
开启注解扫描,即让注解生效
-->
<context:component-scan base-package="com.qf"/>
</beans>
@Test
public void test5(){
String path = "applicationContext3.xml";
// 根据配置文件创建出spring容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(path);
// 从容器中取出对象(默认是类名小写)
Teacher teacher = (Teacher) context.getBean("teacher2");;
System.out.println(teacher );
}
演示2
需求: UserServiceImpl注入UserDao属性
@Repository // 创建对象,取代<bean>
public class UserDaoImpl implements UserDao {
@Override
public void findUserById() {
System.out.println("UserDaoImpl.findUserById");
}
}
@Service // 创建对象,取代<bean>
public class UserServiceImpl implements UserService {
@Autowired // 自动注入,按照类型注入byType
private UserDao userDao;
// 给属性提供set方法
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void findUserById() {
System.out.println("UserServiceImpl.findUserById()执行" );
userDao.findUserById();
}
}
按类型注入,有多个同类型时,注入失败,怎么解决?
@Service
public class UserServiceImpl implements UserService {
// 创建Dao对象
@Autowired // 自动注入,按照类型注入
// 当同类型的对象有多个时,无法自动注入,需要手动指定注入哪个对象
// 使用@Qualifier指定注入的对象名
@Qualifier("userDaoImpl2")
private UserDao userDao;
// ...
}
总结
1 会介绍Spring
2 什么是IOC,DI
3 如何实现IOC和DI
xml实现
<bean id="" class="">
创建对象
<property >
依赖注入注解实现
o.findUserById();
}
}
按类型注入,有多个同类型时,注入失败,怎么解决?
```java
@Service
public class UserServiceImpl implements UserService {
// 创建Dao对象
@Autowired // 自动注入,按照类型注入
// 当同类型的对象有多个时,无法自动注入,需要手动指定注入哪个对象
// 使用@Qualifier指定注入的对象名
@Qualifier("userDaoImpl2")
private UserDao userDao;
// ...
}
总结
1 会介绍Spring
2 什么是IOC,DI
3 如何实现IOC和DI
xml实现
<bean id="" class="">
创建对象
<property >
依赖注入注解实现