一、Spring概述
1.什么是Spring?
Spring是一款轻量级的javaEE应用开源框架(官网: Spring | Home )
2.Spring的开发体现在哪方面?
IOC:通过IOC进行解耦合
AOP:通过切面编程对程序进行增强
粘合剂:Spring是一个超级粘合平台,除了自己提供功能外,还提供整合其他技术和框架的能力
二、Spring IOC基于XML
1.什么是耦合?
耦合是对象之间的依赖关系,对象之间的耦合越高,其代码的维护成本就越高。在没有引入IOC时,系统Web层、Service层和Dao层之间都存在非常高的依赖关系,即都存在耦合。
2.什么是IOC?
IOC(Inverse of Control) 即控制反转:正转是通过自己new新的对象,反转是通过工厂创建对象。
3.工厂模式下的IOC解耦合
- 把Service和Dao对象配置到bean.properties配置文件中.
- 读取bean.properties.
- 把这些对象通过反射创建,并装入容器中.
- 使用时直接从工厂获取.
工厂模式的IOC解耦合:
Dao层:
package com.by.dao;
public interface UserDao {
void addUser();
}
package com.by.dao;
public class UserDaoImpl implements UserDao{
@Override
public void addUser() {
System.out.println("insert into ...");
}
}
Service层:
package com.by.service;
public interface UserService {
void addUser();
}
package com.by.service;
import com.by.dao.UserDao;
import com.by.factory.BeanFactory_v1;
import com.by.factory.BeanFactory_v2;
import com.by.factory.BeanFactory_v3;
public class UserServiceImpl implements UserService{
<!--调用工厂getBean方法获取userDao对象-->
private UserDao userDao= (UserDao) BeanFactory_v3.getBean("userDao");
@Override
public void addUser() {
userDao.addUser();
}
}
创建bean.properties配置文件
userDao=com.by.dao.UserDaoImpl
userService=com.by.service.UserServiceImpl
创建BeanFactory工厂:
package com.by.factory;
import java.io.InputStream;
import java.util.*;
public class BeanFactory_v3 {
//定义一个容器,用于存放对象
private static Map<String, Object> beanMap=new HashMap<>();
//Static是为了提前创建好对象
static {
try {
、//获取文件资源得到一个流
InputStream inputStream = com.by.factory.BeanFactory_v3.class.getClassLoader().getResourceAsStream("bean.properties");
//创建properties对象 读取配置文件
Properties properties=new Properties();
properties.load(inputStream);
//获取key
Set<String> keyset=properties.stringPropertyNames();//等价于keys
for (String key : keyset) {
//利用反射将得到的对象装入容器中
beanMap.put(key, Class.forName(properties.getProperty(key)).newInstance());
}
}catch (Exception e){
e.printStackTrace();
}
}
//创建getBean方法 用于获取容器中的对象
public static Object getBean(String beanName){
return beanMap.get(beanName);
}
}
测试:
package com.by.web;
import com.by.factory.BeanFactory_v1;
import com.by.factory.BeanFactory_v2;
import com.by.factory.BeanFactory_v3;
import com.by.service.UserService;
public class Servlet {
public static void main(String[] args) {
UserService userService= (UserService) BeanFactory_v3.getBean("userService");
userService.addUser();
//查看获取的对象
for (int i = 0; i < 5; i++) {
UserService userService1= (UserService) BeanFactory_v3.getBean("userService");
System.out.println(userService1);
}
}
}
4.IOC下的解耦合
配置pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.by</groupId>
<artifactId>Spring</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>Spring_IOC_Xml</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--引入spring-context依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
</dependencies>
</project>
配置applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入schema约束-->
<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创建
id:给对象在容器提供一个唯一标识 用于获取对象
class:指定类的全限类名 用于反射创建对象。
-->
<bean id="userDao" class="com.by.dao.UserDaoImpl"/>
<bean id="userService" class="com.by.service.UserServiceImpl" >
</bean>
</beans>
测试
package com.by.web;
import com.by.service.UserService;
import com.by.service.UserServiceImpl;
import com.sun.xml.internal.bind.v2.util.XmlFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
public class Servlet {
public static void main(String[] args) {
//1.使用ApplicationContext接口 就是获取spring容器
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
//根据bean的id获取对象
UserService userService = ac.getBean("userService", UserService.class);
userService.addUser();}}
问题:service层仍然耦合
5.DI
什么是DI?
DI依赖注入:把依赖对象(userDao)从容器中(map)拿出来赋值给调用者
DI的三种注入方法
1.构造函数注入:
使用类中的构造函数,给成员变量赋值。注意,赋值的操作不是我们自己做的,而是通过配置的方式,让spring框架来为我们注入。
package com.by.service;
import com.by.dao.UserDao;
public class UserServiceImpl implements UserService{
private UserDao userDao;
public UserServiceImpl() {
System.out.println("UserServiceImpl被创建了");
}
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入schema约束-->
<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创建
id:给对象在容器提供一个唯一标识 用于获取对象
class:指定类的全限类名 用于反射创建对象。
-->
<bean id="userDao" class="com.by.dao.UserDaoImpl"/>
<bean id="userService" class="com.by.service.UserServiceImpl" autowire="byType" scope="prototype" init-method="init" destroy-method="destroy" >
<!--
1.构造方法
name:给谁赋值:构造方法中的参数名称
ref:赋什么值 配置bean中的值-->
<constructor-arg name="userDao" ref="userDao"/>
</bean>
</beans>
2.Set方法注入
在类中提供需要注入成员的set方法。
package com.by.service;
import com.by.dao.UserDao;
public class UserServiceImpl implements UserService{
private UserDao userDao;
public void setUserDao(UserDao userDao) {
System.out.println("set方法注入bean");
this.userDao = userDao;
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入schema约束-->
<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创建
id:给对象在容器提供一个唯一标识 用于获取对象
class:指定类的全限类名 用于反射创建对象。
-->
<bean id="userDao" class="com.by.dao.UserDaoImpl"/>
<bean id="userService" class="com.by.service.UserServiceImpl" autowire="byType">
<!--2.Set方法
name:Set方法后面的部分
ref:bean中的值-->
<property name="userDao" ref="userDao"/>
3.自动注入
不用在配置中 指定为哪个属性赋值,由spring自动根据某个 "原则" ,在工厂中查找一个bean并为属性注入值。
package com.by.service;
import com.by.dao.UserDao;
public class UserServiceImpl implements UserService{
private UserDao userDao;
//提供Set方法 在xml配置自动注入
public void setUserDao(UserDao userDao) {
System.out.println("set方法注入bean");
this.userDao = userDao;
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入schema约束-->
<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创建
id:给对象在容器提供一个唯一标识 用于获取对象
class:指定类的全限类名 用于反射创建对象。
autowire:自动识别类型
-->
<bean id="userDao" class="com.by.dao.UserDaoImpl"/>
<bean id="userService" class="com.by.service.UserServiceImpl" autowire="byType"/>
6.BeanFactory和ApplicationContext的区别
BeanFactory:顶级接口,getBean()时创建对象
ApplicationContext:子接口,直接创建对象
7.Spring bean的作用范围(bean放哪儿了)
singleton:单例,IOC容器
prototype:多例,每次都创建
request:request域
session:session域
application:servletContext域
单例和多例的使用场景?
单例:seervice、dao、sqlsessionFactory
多例:connection、SqlSession
8.Spirng bean的生命周期
单例:
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入schema约束-->
<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创建
id:给对象在容器提供一个唯一标识 用于获取对象
class:指定类的全限类名 用于反射创建对象。
scope:作用范围
init:调用init初始化
destroy:调用destory销毁bean
-->
<bean id="userDao" class="com.by.dao.UserDaoImpl"/>
<bean id="userService" class="com.by.service.UserServiceImpl" autowire="byType" scope="singleton" init-method="init" destroy-method="destroy" >
package com.by.service;
import com.by.dao.UserDao;
public class UserServiceImpl implements UserService{
private UserDao userDao;
public UserServiceImpl() {
System.out.println("UserServiceImpl被创建了");
}
public void setUserDao(UserDao userDao) {
System.out.println("set方法注入bean");
this.userDao = userDao;
}
public void init(){
System.out.println("这是调用init()初始化bean");
}
public void destroy(){
System.out.println("这是调用destroy销毁bean");
}
@Override
public void addUser() {
userDao.addUser();
}}
多例:
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入schema约束-->
<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创建
id:给对象在容器提供一个唯一标识 用于获取对象
class:指定类的全限类名 用于反射创建对象。
scope:作用范围
init:调用init初始化
destroy:调用destory销毁bean
-->
<bean id="userDao" class="com.by.dao.UserDaoImpl"/>
<bean id="userService" class="com.by.service.UserServiceImpl" autowire="byType" scope="prototype" init-method="init" destroy-method="destroy" >
三、基于注解的IOC配置
1.常见注解
1)IOC注解
@Controller:web
@Servce:service
@Repository:dao
@Conponent:三层架构之外
@Scope:指定bean的作用域范围
2)DI注解
@Ressource(name=""):按名称注入,即按map的key获取对象
@Autowired:按类型注入
@Value:注入基本类型
2.IOC注解案例
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.by</groupId>
<artifactId>Spring</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>Spring_IOC_Annotation</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
</dependencies>
</project>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd ">
<context:property-placeholder location="config.properties"></context:property-placeholder>
<context:component-scan base-package="com.by" ></context:component-scan>
</beans>
dao层:
package com.by.dao;
public interface UserDao {
void addUser();
}
package com.by.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
//把资源交给Spring相当于<bean id="" class="">
//属性:value指定bean的id 如果不指定value值 默认bean的id为当前类名 首字母小写
@Repository //声明bean id=“userDaoImpl”
public class UserDaoImpl implements UserDao{
@Override
public void addUser() {
System.out.println("insert into...");
}
}
service层
package com.by.service;
public interface UserService {
void addUser();
}
package com.by.service;
import com.by.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service声明bean,且id="userServiceImpl"
public class UserServiceImpl implements UserService{
@Autowired//自动注入类型为UserDao的bean
private UserDao userDao;
@Value("${msg}") //注入String 注入基本数据类型和String类型数据的
private String msg;
@Value("${num}")
private Integer num;
@Override
public void addUser() {
System.out.println(msg+"------------------"+num);
userDao.addUser();
}
}