Spring
Spring是一个轻量级
的控制反转(IoC)
和面向切面(AOP)
的容器框架。
轻量——从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。
控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。
如何理解控制翻转?
搭建Spring环境
1、由于目前还未牵涉到浏览器,因此创建maven-java项目即可
2、导入依赖
<dependencies>
<!-- spring-context依赖中关联了其他核心依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
</dependencies>
3、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>
入门案例-IOC
IOC: Inversion of control 控制反转,以前对象创建的控制权在自己,现在将控制权交给Spring,由Spring框架创建对象
需求:现有一接口UserService,有一实现类UserServiceImpl,使用接口直接调用方法让其执行。
UserService接口:
package com.lyc.service;
public interface UserService {
void findUser();
}
UserServiceImpl实现类:
package com.lyc.service.impl;
import com.lyc.service.UserService;
public class UserServiceImpl implements UserService {
@Override
public void findUser() {
System.out.println("UserServiceImpl.findUser()执行" );
}
}
applicationContext.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配置文件applicationContext.xml相当于是
一个容器,在这里配置整个项目中所需要的对象
-->
<!-- 一个bean标签代表一个类,会创建该类对象
class 是要交给Spring创建对象的类路径
id 是创建完成后的对象名
-->
<bean id="userService" class="com.qf.service.impl.UserServiceImpl"/>
</beans>
测试类:
public class TsetIOC {
@Test
public void test(){
String path = "applicationContext.xml";
// 根据配置文件创建出spring容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(path);
// 从容器中取出对象(根据对象名获得对象,配置文件中的id)
UserService userService = (UserService) context.getBean("userService");
userService.findUser();
}
}
依赖注入(DI)(属性赋值)
依赖注入其实就是给属性赋值
在JavaWeb阶段,我们知道在Service层调用dao层,就需要在ServiceImpl类中,new一个dao层对象。
现在我们使用Spring框架,来改变这种方式。
dao
//接口
public interface UserDao {
void findUserById();
}
//实现类
package com.lyc.dao.impl;
import com.lyc.dao.UserDao;
public class UserDaoImpl implements UserDao {
public void findUser() {
System.out.println("UserDaoImpl");
}
}
UserServiceImpl:
public class UserServiceImpl implements UserService {
/**
* JavaWeb阶段在Service层调用Dao层
* UserDaoImpl userDao = new UserDaoImpl();
* userDao.findUser();
*/
//Spring阶段是在ServiceImpl这里提供UserDao的对象属性
private UserDao userDao;
//在设置UserDao对象属性的同时还要设置它的set方法,否则会报错
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void findUser() {
System.out.println("UserServiceImpl.findUser()执行" );
userDao.findUser();
}
}
applicationContext.xml
<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"/>
注意:给属性赋值
必须要有set方法
。
测试:
@Test
public void test(){
String path = "applicationContext.xml";
// 根据配置文件创建出spring容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(path);
// 从容器中取出对象(根据对象名获得对象)
UserService userService = (UserService) context.getBean("userService");
userService.findUser();
}
依赖注入-Set方式
实体类:
package com.lyc.model;
import java.util.*;
public class User {
//单个属性赋值
private String name;
private int age;
private Date birthday;
//数组、list、set、map集合赋值
private String[] address;
private List<String> phone;
private Set<String> car;
private Map<String,String> children;
//对象属性赋值
private Cat cat;
public User() {
}
public String[] getAddress() {
return address;
}
public void setAddress(String[] address) {
this.address = address;
}
public List<String> getPhone() {
return phone;
}
public void setPhone(List<String> phone) {
this.phone = phone;
}
public Set<String> getCar() {
return car;
}
public void setCar(Set<String> car) {
this.car = car;
}
public Map<String, String> getChildren() {
return children;
}
public void setChildren(Map<String, String> children) {
this.children = children;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", birthday=" + birthday +
", address=" + Arrays.toString(address) +
", phone=" + phone +
", car=" + car +
", children=" + children +
", cat=" + cat +
'}';
}
}
Cat:
package com.lyc.model;
public class Cat {
private String name;
private int age;
private String color;
public Cat() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
'}';
}
}
applicationContext.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDao" class="com.lyc.dao.impl.UserDaoImpl" />
<!--创建Cat对象-->
<bean id="cat" class="com.lyc.model.Cat">
<property name="name" value="咪咪"/>
<property name="age" value="2"/>
<property name="color" value="橘色"/>
</bean>
<!--创建User对象-->
<bean id="User" class="com.lyc.model.User">
<!--单个属性赋值-->
<property name="name" value="李思" />
<property name="age" value="21" />
<property name="birthday" value="2022/9/23" />
<!--数组-->
<property name="address">
<array>
<value>xx省</value>
<value>xx市</value>
<value>xx县</value>
</array>
</property>
<!--list集合-->
<property name="phone">
<list>
<value>110</value>
<value>110</value>
<value>120</value>
<value>119</value>
</list>
</property>
<!--set集合-->
<property name="car">
<set>
<value>劳斯莱斯</value>
<value>劳斯莱斯</value>
<value>玛莎拉蒂</value>
<value>迈巴赫</value>
</set>
</property>
<!--map集合-->
<property name="children">
<map>
<entry key="1" value="大儿子"></entry>
<entry key="2" value="二儿子"></entry>
<entry key="3" value="小儿子"></entry>
</map>
</property>
<!--引用对象属性-->
<property name="cat" ref="cat" />
</bean>
</beans>
注解实现IOC-DI【重点】
常用的注解:
注解 | 作用 | 位置 | 被替代的标签 |
---|---|---|---|
@Component | 创建对象 | 一般在实体类 | |
@Controller | 创建对象 | 控制层的类上 | |
@Service | 创建对象 | 业务层的类上 | |
@Repository | 创建对象 | 持久层(数据层)的类上 | |
@Value | 给基本类型属性赋值 | 属性上 | |
@Autowired | 给引用类型属性赋值 | 属性上 |
虽然@Component,@Controller,@Service,@Repository都是用来创建对象,只不过建议是在相应的位置使用相应的注解
案例演示:
实体类:
Student:
package com.lyc.model;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Component
public class Student {
@Value("王宝")
private String name;
@Value("16")
private int age;
@Value("88.0")
private double score;
private String[] address;
private List<String> subject;
private Set<String> teacher;
private Map<String,String> parent;
@Autowired
private Teacher teacher1;
public Teacher getTeacher1() {
return teacher1;
}
public void setTeacher1(Teacher teacher1) {
this.teacher1 = teacher1;
}
public String[] getAddress() {
return address;
}
public void setAddress(String[] address) {
this.address = address;
}
public List<String> getSubject() {
return subject;
}
public void setSubject(List<String> subject) {
this.subject = subject;
}
public Set<String> getTeacher() {
return teacher;
}
public void setTeacher(Set<String> teacher) {
this.teacher = teacher;
}
public Map<String, String> getParent() {
return parent;
}
public void setParent(Map<String, String> parent) {
this.parent = parent;
}
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
", address=" + Arrays.toString(address) +
", subject=" + subject +
", teacher=" + teacher +
", parent=" + parent +
", teacher1=" + teacher1 +
'}';
}
}
Teacher:
package com.lyc.model;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Teacher {
@Value("牛彩云")
private String tname;
@Value("18")
private int tage;
@Value("语文")
private String tsubject;
public Teacher() {
}
public String getTname() {
return tname;
}
public void setTname(String tname) {
this.tname = tname;
}
public int getTage() {
return tage;
}
public void setTage(int tage) {
this.tage = tage;
}
public String getTsubject() {
return tsubject;
}
public void setTsubject(String tsubject) {
this.tsubject = tsubject;
}
@Override
public String toString() {
return "Teacher{" +
"tname='" + tname + '\'' +
", tage=" + tage +
", tsubject='" + tsubject + '\'' +
'}';
}
}
dao:
//接口
package com.lyc.dao;
public interface StudentDao {
void queryStudent();
}
//实现类
package com.lyc.dao.impl;
import com.lyc.dao.StudentDao;
import org.springframework.stereotype.Repository;
@Repository
public class StudentDaoImpl implements StudentDao {
public void queryStudent() {
System.out.println("StudentDaoImpl.queryStudent()执行了");
}
}
serviec:
//接口
package com.lyc.service;
public interface StudentService {
void queryStudent();
}
//实现类
package com.lyc.service.impl;
import com.lyc.dao.StudentDao;
import com.lyc.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
public StudentDao getStudentDao() {
return studentDao;
}
public void setStudentDao(StudentDao studentDao) {
this.studentDao = studentDao;
}
public void queryStudent() {
System.out.println("StudentServiceImpl.queryStudent()执行行了");
studentDao.queryStudent();
}
}
applicationContext.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解-->
<context:component-scan base-package="com.lyc.*"/>
</beans>
我们使用了注解来实现IOC-DI,但是Spring默认没有开启注解,因此我们需要在配置文件中开启注解扫描
测试类:
package com.lyc;
import com.lyc.model.Student;
import com.lyc.service.StudentService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void student(){
//注解式开发
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student) context.getBean("student");
System.out.println(student);
}
@Test
public void query(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
StudentService studentService = (StudentService) context.getBean("studentServiceImpl");
studentService.queryStudent();
}
}