Spring入门篇

Spring Frameword

  • Spring Framework是Spring生态圈中最基础的项目,是其他项目的根基

image-20230228222030434

1.1 Spring Frameword系统架构图

image-20230228222340217

1.2 Spring Frameword学习路线

image-20230228222518098

1.3 核心概念

  • 代码现状
    • 耦合度偏高
  • 解决方案
    • 使用对象时,在程序中不要主动new产生对象,转换为由外部提供对象
  • IoC(Inversion of Control)控制反转
    • 对象的创建控制权由程序转到外部,这种思想为控制反转

image-20230228222947261

1.3.1 IoC ( Inversion of Control ) 控制反转

  • 使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转

1.3.2 Spring技术对IoC思想进行了实现

  • Spring提供了一个容器,称为IoC容器用来充当IoC思想中的“外部”
  • IoC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IOC容器中统称为Bean

1.3.3 DI ( Dependency Injection ) 依赖注入

  • 在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入

image-20230228223319579

1.3.4 目标:充分解耦

  • 使用IoC容器管理bean (IoC)
  • 在IoC容器内将有依赖关系的bean进行关系绑定 (DI)

1.3.5 最终效果

  • 使用对象时不仅可以直接从IoC容器中获取,并且获取到的bean已经绑定了所有的依赖关系

1.4 IoC入门

  1. 导入Spring坐标
<dependency>
     <groupId>org.springframeword</groupId>
     <artifactId>spring-context</artifactId>
     <version>5.2.10.RELEASE</version>
</dependency>
  1. 定义Spring管理的类(接口)
public interface BookService{
	public void save();
}
public class BookServiceImpl implements BookService {

	private BookDao bookDao = new BookDaoImpl();
	
	public void save(){
		boolDao.save();
	}
}
  1. 创建Spring配置文件,配置对应类作为Spring管理的bean
<?xml version="1.” encoding="UTF-8"?>
<beans xmIns="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="bookService"class="com.itheima.service.impl.BookServiceImpl"></bean>

</beans>

注意事项:bean 定义时id属性在同一个上下文中不能重复

  1. 初始化IoC容器 ( Spring核心容器/Spring容器 ),通过容器获取bean
public class App {
	public static void main(String[] args) {
		//加载配置文件得到上下文对象,也就是容器对象
    	ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取资源
		BookService bookService = (BookService)tx.getBean("bookService");
    	bookService.save();
}

image-20230513002339309

1.4.1 bean作用范围说明

  • bean默认为单例
  • 适合交给容器进行管理的bean
    • 表现层对象
    • 业务层对象
    • 数据层对象
    • 工具对象
  • 不适合交给容器进行管理的bean
    • 封装实体的域对像

1.4.2 bean实例化

1.4.2.1 使用构造方法实例化bean(常用)

<bean id="bookDao”class="com.itheima.dao.impl.BookDaoImpl"/>                             

1.4.2.2 使用静态工厂实例化bean(了解)

<bean id="orderDaoclass="com. itheima,factory.0rderDaoFactory" factory-method="getOrderDao"/>

1.4.2.3 使用实例工厂实例化bean(了解)

<bean id="userFactory" class="com.itheima.factory.UserDaoFactory"/>

<bean id="userDao"factory-method="getUserDao" factory-bean="userFactory"/>

1.4.2.4 使用FactoryBean实例化bean(需要掌握)

<bean id="userDao”class="com.itheima.factory.UserDaoFactoryBean"/>
public class UserDaoFactoryBean implements FactoryBean<UserDao>{
    //代替原始实例工厂中创建对象的方法
    public UserDao getObject() throws Exception{
        return new UserDaoImpl();
    }
    
    public class<?> getobjectType() {
        return UserDao.class;
    }
    
    public boolean isSingleton() {
        //若为true就是单例,false就是非单例
        return true;
    }
}
     

1.4.3 bean的生命周期

  • 生命周期:从创建到消亡的完整过程
  • bean生命周期:bean从创建到销毁的整体过程
  • bean生命周期控制:在bean创建后到销毁前做一些事情

bean管理的BookDao类:

public class BookDaoImpl implements BookDao {
    public void save() {
		System.out.printIn("book dao save...");
    }
	//表示bean初始化对应的操作
    public void init(){
        System.out.printIn("init...");
    }
	//表示bean 销毁前对应的操作
    public void destory(){
        System.out.printIn("destory...");
    }

ApplicationContext xml文件配置信息:

<!---配置bean的生命周期
	初始化时调用方法: init-method
	销毁时调用方法:destroy-method
--->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>

Main:

public class AppForLifeCycle{
	public static void main( String[] args ) {
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml")
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.save();
		ctx.close();
}

以上是bean的暴力关闭方法!

还有一种设置关闭钩子的方法:

Main:

public class AppForLifeCycle{
	public static void main( String[] args ) {
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml")
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.save();
        ctx.registershutdownHook();//这就是设置关闭钩子
		/*设置关闭钩子方法相比close更加安全方便,若close在关闭对象的调用方法的前面,那对象都被暴力关闭了,后面调用其方法也会报错!
		ctx.close();
}

image-20230513233839088
image-20230513234117652
image-20230513234129376
image-20230513234155342
image-20230513234234431

1.5 依赖注入

思考:向一个类中传递数据的方式有几种 ?

  • 普通方法 (set方法)
  • 构造方法

思考:依赖注入描述了在容器中建立bean与bean之间依赖关系的过程,如果bean运行需要的是数字或字符串呢?

  • 引用类型
  • 简单类型(基本数据类型与string )

1.5.1 setter注入

1.5.1.1 引用类型注入

在bean中定义引用类型属性并提供可访问的set方法

public class BookServiceImpl implements BookService{
    private BookDao bookDao;
    public void setBookDao(BookDao bookDao){
        this.bookDao = bookDao;
    }
}

配置中使用property标签ref属性注入引用类型对象

<bean id="bookService" class="com,itheima,serwice.impl.BookServiceImpl">
    <property name="bookDao" ref="bookDao"/>
</bean>
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>

1.5.1.2 简单类型注入

在bean中定义引用类型属性并提供可访问的set方法

public class BookDaoImpl implements BookDao {
	private int connectionNumber;
	public void setConnectionNumber(int connectionNumber) {
		this.connectionNumber = connectionNumber;
	}
}

配置中使用property标签value属性注入简单类型数据

<bean id="bookDao" class="com.itheima,dao.impl.BookDaoImpl">
    <property name="connectionNumber" value="10"/>
</bean>

1.5.2 构造器注入

1.5.2.1 引用类型

在bean中定义引用类型属性并提供可访问的构造方法

public class BookServiceImpl implements BookService{
    private BookDao bookDao;public BookServiceImp1(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}

配置中使用constructor-arg标签ref属性注入引用类型对象

<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
    <constructor-arg name="bookDao" ref="bookDao"/>
</bean>
<bean id="bookDao"class="com.itheima.dao.impl.BookDaoImpl"/>

1.5.2.1 简单类型

在bean中定义引用类型属性并提供可访问的set方法

public class BookDaoImpl implements BookDao{
    private int connectionNumber;
    public void setConnectionNumber(int connectionNumber) {
        this.connectionNumber = connectionNumber;
    }
} 

配置中使用constructor-arg标签value属性注入简单类型数据

<bean id="bookDao"class="com,itheima.dao.impl.BookDaoImpl">
    <constructor-arg name="connectionNumber" value="10"/>
</bean>

配置中使用constructor-arg标签type属性设置按形参类型注入

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
    <constructor-arg type="int" value="19"/>
    <constructor-arg type="java.lang.String" value="mysql"/>
</bean>

配置中使用constructor-arg标签index属性设置按形参位置注入

<bean id = "bookDao" class = "com.itheima.dao.impl.BookDaoImpl">
    <constructor-arg index = "0" value = "10"/>
    <constructor-arg index = "1" value = "mysql"/>
</bean>

1.5.3 依赖注入的选择:

  1. 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致nul1对象出现

  2. 可选依赖使用setter注入进行,灵活性强

  3. Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨

  4. 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入

  5. 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入

  6. 自己开发的模块推荐使用setter注入

1.5.3.1 依赖自动装配:

  • IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配
  • 自动装配方式
    • 按类型(常用)
    • 按名称
    • 按构造方法
    • 不启动自动装配
<bean id="bookService"class="com.itheima,service.impl.BookServiceImpl" autowire="byName"/>

autowire:就是配置自动装配的属性标签

1.5.3.1.1 自动装配的特征:
  • 自动装配用于引用类型依赖注入,不能对简单类型进行操作
  • 使用按类型装配时 ( byType ) 必须保障容器中相同类型的bean唯一,推荐使用
  • 使用按名称装配时( byName)必须保障容器中具有指定名称的bean,因变量名与配置合,不推荐使用
  • 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效

1.5.4 集合注入

数组:List、Set、Map、Properties

  • 注入数组对象
<property name="array">
	<array>
        <value>100</value>
        <value>200</value>
        <value>300</value>
	</array>
</property>
  • 注入List对象(重点)
<property name="list">
	<list>
		<value>itcast</value>
        <value>itheima</value>
        <value>boxuegu</value>
	</list>
</property>
  • 注入set对象
<property name="set">
	<set>
		<value>itcast</value>
        <value>itheima</value>
        <value>boxuegu</value>
	</set>
</property>
  • 注入Map对象(重点)
<property name="map">
	<map>
 		<entry key="country" value="china"/>
        <entry key="province" value="henan"/>
		<entry. key="city" value="kaifeng"/>
	</map>
</property>
  • 注入Properties对象
<property name="properties">
	<props>
		<prop key="country">china</prop>
        <prop key="province">henan</prop>
        <prop key="city">kaifeng</prop>
	</props>
</property>

1.6 第三方数据源管理

1.6.1 数据源对象管理

  • 导入druid坐标
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>1.1.16</version>
</dependency>
  • 配置数据源对象作为spring管理的bean
<bean id="dataSource" class="com,alibaba.druid.pool.DruidDataSource">
  <property name="driverClassName” value="com.mysql.jdbc.Driver"/>
  <property name="url" value="jdbc:mysql://127.0.0.1:3306/spring_db"/>
  <property name="username" value="root"/>
  <property name="password" value="root"/>
</bean>

1.7 加载properties文件

1.7.1 在applicationContext中开辟新的命名空间(context空间)

  • 技巧:改空间分改五步
  <beans xmIns="http://www.springframework.org/schema/beans"
xmIns:xsi="http://www.w3.org/2001/XMLSchema-instance"

<!-- xmIns:context…… and ……/schema/context 中的两处context -->

xmIns:context="http://www.springframework.org/schema/context'
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
<!-- ……/schema/context and ……/context/spring-context.xsd 中的三处context -->
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">

1.7.2 使用context空间加载properties文件

  <context:property-placeholder location="jdbc.properties"/>

1.7.3 使用属性占位符${}读取properties文件中的属性

<bean class="com.alibaba.druid.pool.DruidDataSpurce">
  <property name="driverClassName" value="${jdbc.driver}"/>
  <property name="url" value="${jdbc.url}"/>
  <property name="username" value="${jdbc.username}"/>
  <property name="password" value="${jdbc.password}"/>
</bean>

1.7.4 加载多个properties文件

<context:property-placeholder location="classpath:*.properties" system-properties-mode="NEVER"/>
<!-- 在location中添加多个properties即可 -->
<!-- 补充说明,如果系统注入的配置属性与自写的冲突时,可以在system-properties-mode中设置系统属性为NEVER,不加载 -->

1.8 容器

1.8.1 创建容器

  • 方式一:类路径加载配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext,xml");
  • 方式二:文件路径加载配置文件
ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\applicationContext,xml");
  • 加载多个配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml", "bean2.xml");

1.8.2 获取bean

  • 方式一:使用bean名称获取
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
  • 方式二:使用bean名称获取并指定类型
BookDao bookDao = ctx.getBean("bookDao",BookDao.class);
  • 方式三:使用bean类型获取
BookDao bookDao = ctx.getBean(BookDao.class);


1.9 总结



1.10 注解开发

1.10.1 用component注解配置bean

  • 第一步在bean的类上加上@component注解

  • 在properties文件中的context命名空间中进行component的scan

  <context:component-scan base-package="com.itheima.hao.impl"/>
  • Spring提供@Component注解的三个衍生注解

1.10.2 纯注解开发

  • @Configuration这个注解可以代替properties文件
  • @ComponentScan("com.itheima")这个可以代替<context:component-scan base-package="com.itheima.hao.impl"/>
  • 最后创建容器对象ApplicationContext ctx = new AnnotationConfigApplicationContextSpringConfig.class);

1.10.3 总结



1.10.4 注解开发bean的生命周期&作用范围


1.10.5 依赖注入

1.10.5.1 引用类型注入

  • @Autowired注解来自动按类型注入

在使用Autowired时有点打破IOC的思想,因为Autowired可以不用提供set入口方法,而是通过暴力反射来注入的

  • 在有同类型的bean时想注入就要用按名称来注入了,@Qualifier("bookDao2")这个注解就可以实现

@Qualifier("beanName")记住这个注解是依赖Autowired注解的


1.10.5.2 简单类型注入

1.10.5.2 properties文件属性注入

  • 第一步在配置类中用PropertySource注解来加载properties文件
  • 第二步用@Value("${name}")就可以注入

1.10.6 纯注解管理第三方bean

  • 导入式
  • 扫描式

1.10.7 纯注解bean依赖注入


1.10.8 XML配置对比注解配置

1.11 spring整合mybatis

  • 坐标
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>5.2.1.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>1.3.</version>
</dependency>

1.12 Spring整合junit

  • 导两个包
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
  <scope>test</scope>
</dependency>

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>5.2.10.RELEASE</version>
</dependency>
  • 使用spring整合junit专用的类加载器

1.13 AOP

  • 面向切面编程,一种编程范式,指导开发者如何组织程序结构
  • 作用:在不惊动原始设计的基础上为其进行功能增强
  • Spring理念:无入侵式/无侵入式

  • 连接点(JoinPoint ):程序执行过程中的任意位置,粒度为执行方法、抛出异常、设置变量等
    • 在SpringAOP中,理解为方法的执行
  • 切入点( Pointcut ):匹配连接点的式子
    • 在springAOP中,一个切入点可以只描述一个具体方法,也可以匹配多个方法
      • 一个具体方法:com.itheima.dao包下的BookDao接口中的无形参无返回值的save方法
      • 匹配多个方法:所有的save方法,所有的get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有一个参数的方法
  • 通知(Advice):在切入点处执行的操作,也就是共性功能
    • 在springAOP中,功能最终以方法的形式呈现
  • 通知类:定义通知的类
  • 切面(Aspect ): 描述通知与切入点的对应关系

1.13.1 APO快速入门(注解版)

1.13.1.1 导入aop相关的坐标

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.2.10.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.4</version>
</dependency>

1.13.1.2 定义接口和实现类

public interface BookDao {
  public void save();
  public void update();
}
@Repository
public class BookDaoImpl implements BookDao {
  public void save() {
    System.out.printIn(System.currentTimeMillis());
    System.out.println("book dao save ...");
  }
  public void update(){
    System.out.println("book dao update ...");
  }
}

1.13.2 切入点表达式

  • 切入点表达式标准格式:动作关键字( 访问修饰符 返回值 包名.类/接口名.方法名( 参数 )异常名

1.13.3 AOP的通知类型

  • AOP通知描述了抽取的共性功能,根据共性功能抽取的位置不同,最终运行代码时要将其加入到合理的位置

  • AOP通知共分为5种类型

    • 前置通知
    • 后置通知
    • 环绕通知(重点)

重点,常用

  • 返回后通知(了解)
  • 抛出异常后通知(了解)

1.13.4 AOP通知获得参数数据

1.13.5 AOP获得返回值数据

1.13.6 AOP通知获得异常数据(了解)

1.13.7 AOP处理数据案例

posted @ 2023-10-11 01:25  Cold的窝  阅读(25)  评论(0)    收藏  举报