欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring

程序员文章站 2022-07-12 13:02:56
...

1.Spring概述

1)spring是什么

JAVAEE企业应用轻量级开源框架,以IOC和AOP为内核,提供展现层SpringMVC和持久层SpringJDBC以及业务层声明式事务处理的技术,可以整合第三方框架和类库。

2)spring两大核心

2.1> IOC控制反转

2.2> AOP面向切面编程

3)spring体系结构

spring

2.程序的耦合与解耦

1)耦合方式:

1> 程序间的依赖:

1.类之间的依赖

​ 业务层依赖持久层,持久层依赖实体类。spring

2.方法间的依赖

2)解耦

1> 降低程序之间的依赖

方法:编译时不依赖,运行时才依赖

思路:1.使用反射来创建对象,而避免使用new关键字。

​ 2.通过读取配置文件来获取要创建对象的全限定类名

2)工厂模式解耦

1> 一个创建Bean对象的工厂

Bean:可重用组件的意思

​JAVABean:用java语言编写的可重用组件

​		javabean > 实体类pojo

​ 这个工厂来创建我们的业务层service和持久层dao对象

​ 1.通过一个配置文件配置我们想需要的service和dao

​ 配置内容大概为:唯一标识key=全限定类名value

​ 2.通过读取这个配置文件中配置的内容,使用反射创建对象

​ 配置文件可以为xml和properties和yml

3.IOC与Spring中的IOC

IOC:控制反转 (Inversion of Control)将创建对象的权利交给工厂,包括依赖注入DI(dependency injection)和依赖查找DL(Dependency Lookup)

​ 作用:降低依赖关系。
spring

1)Spring的基于XML的IOC环境搭建

spring
spring

2)ApplicationContext的三个常用的实现类

​ ClassPathXmlApplicationContext:可以加载类路径下的配置文件(常用)

​ FileSystemXmlApplicationContext:可以加载磁盘任意路径下的配置文件(必须有访问权限)

​ AnnotationConfigApplicationContext:用于读取注解创建容器

3)核心容器的两个接口引发的问题

1.ApplicationContext:单例对象适用

​ 构建核心容器时,创建对象采取的策略是立即加载的方式,–>不管用没用,我都先创建对象

2.BeanFactory:多例对象适用

​ 构建核心容器时,创建对象采用的是延迟加载的方式,–>什么时候根据id获取对象,什么时候创建对象。

4)Spring对bean的管理细节

1>创建bean的三种方式

​ 1.使用默认的构造函数创建bean

​ 在Spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他的属性时,采用的就是默认的构造函数创建对象,此时类中没有默认的无参构造函数,则对象无法创建。

<bean id="StudentService" class="com.jsl.service.impl.StudentServiceImpl"></bean>

​ 2.使用普通工厂中的方法创建对象(使用某个类中的方法创建对象并存入spring容器中)

<bean id="InstanceFactory" class="com.jsl.factory.InstanceFactory"></bean>
<bean id="StudentService" factory-bean="InstanceFactory" 
   factory-method="getStudentService"></bean>

​ 3.使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象,并存入spring容器中)

<bean id="StudentService" class="com.jsl.factory.StaticInstanceFactory" 
    	factory-method="getStudentService"></bean>

2>bean对象的作用范围

  • bean标签的作用范围调整

    • bean标签的scope属性:

      • 作用:指定bean的作用范围

      • 取值:

        • singleton:单例(默认值)
        • prototype:多例
        • request:作用于WEB应用的请求范围
        • session:作用于WEB应用的会话范围
        • global-session:作用于集群环境的会话范围(全局会话范围),当不是集群时,他就是session
          spring

3>bean对象的生命周期

​ 1.单例对象

​ 出生:容器创建,对象出生

​ 活着:容器存在,对象存活

​ 死亡:容器销毁,对象死亡

​ 总结:单例对象和容器共存亡

​ 2.多例对象

​ 出生:当使用对象时,对象出生

​ 活着:对象一直在被使用,对象存活

​ 死亡:长时间不用,java的垃圾回收机制进行回收

​ 总结:单例对象和容器共存亡

4.依赖注入DI

1)什么是依赖注入(Dependency Injection)

在当前类需要用到其他类的对象,有spring为我们提供这个类的对象,我们只需要在spring的配置文件中说明这个依赖关系,这个过程称为依赖注入。

2)三类可注入的数据

​ 1.基本类型和String

​ 2.其他bean类型(在配置文件中或者注解配置过得bean)

​ 3.复杂类型、集合类型

3)三种注入方式

1>.使用构造函数

​ 使用的标签:constructor-arg

​ 标签出现的位置:bean标签的内部

​ 标签中的属性:

​ type:用于指定注入的数据的数据类型,该数据类型也是构造函数中的某个或者某些参数的类型

​ name:用于给构造函数中制定名称的参数赋值

​ index:用于指定构造函数中指定索引位置的参数赋值,索引位置从0开始

​ value:用于提供基本类型和String类型的数据

​ ref:用于指定其他的bean类型数据,即在ioc容器中出现过的bean对象

​ PS:spring不能自动转日期格式的字符串,所以要引用一个日期对象

​ 优劣:+ 在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功。

​ - 改变了bean对象的实例化方式,使我们创建对象时,若用不到这些数据也必须提供

<bean id="hs2" class="com.yh.spring.HelloSpring">
	<!-- 构造方法注入/ 参数下标index/参数类型 -->
	<constructor-arg type="java.lang.Integer">
		<value>888</value>
	</constructor-arg>
	<constructor-arg value="world" type="java.lang.String"></constructor-arg>
	<constructor-arg value="world" name="name"></constructor-arg>
	<constructor-arg value="18" name="age"></constructor-arg>
	<constructor-arg ref="now" name="date"></constructor-arg>
</bean>
<!--配置一个java日期对象-->
<bean id="now" class="java.util.Date"></bean>

2>.使用setter方法

使用的标签:property

出现的位置:bean标签内部

标签的属性:

​ name:用于指定注入时所调用的set方法名称 -------------------->Set方法的名字

​ value:用于提供基本类型和String类型

​ ref:用于指定其他bean类型,即IOC容器中出现过得bean对象

优劣:+创建对象没有明确的限制,直接使用默认的构造函数

​ -

<bean id="hs1" class="com.yh.spring.HelloSpring">
	<!-- setter注入,需要有无参构造方法 -->
	<property name="who" value="Spring"></property>
	<property name="i" value="999"></property>
</bean>

3>.复杂类型的注入、集合类型的注入

​ 用于给List结构集合诸如的标签:list,array,set

​ 用于Map结构集合注入的标签:map,props

​ 结构相同,标签可以互换。

<bean id="hs1" class="com.yh.spring.HelloSpring">
	<!-- setter注入,需要有无参构造方法 -->
	<property name="set" >
		<list>
			<value>aaa</value>
    	</list>
    </property>
	<property name="array">
		<array>
			<value>aaaa</value>
    	</array>
    </property>
    
    <property name="map" >
		<map>
			<entry key="test">aaa</entry>
    	</map>
    </property>
	<property name="prop">
		<props key="testA">
			<prop>aaaa</prop>
    	</props>
    </property>
</bean>

4>.使用注解提供

5.Spring基于注解的IOC

1)spring中IOC常用的注解

注解配置和xml文件配置的实现功能都是一致的。

1>.xml配置所实现的功能

<bean id="hs2" class="com.yh.spring.HelloSpring" scope="" 
      init-method="" destroy-method="">
	<constructor-arg value="18" name="age"></constructor-arg>
	<constructor-arg ref="now" name="date"></constructor-arg>
</bean>

2>.注解配置归类

1.用于创建对象

​ 和xml中的bean标签实现的功能一致

​ 1.Component

​ 注解位置:要注入容器中的类名上

​ 作用:用于将当前类存入spring容器中

​ 属性:value:用于指定bean的id,当不写时,默认值为类名,首字母小写

​ PS:以下三个注解和Component注解的作用和属性是一模一样,只是spring为我们提供三层明确的对象

​ 2.Controller:一般用在表现层

​ 3.Service:一般用在业务层

​ 4.Repository:一般用在持久层

2.用于注入数据

和xml中的bean标签中的属性标签实现的功能一致

aaa@qq.com:

  • 作用:
    • 按照类型自动注入,只要容器中有唯一一个bean对象类型和要注入的变量类型匹配,就可注入成功。
    • 若ioc容器中没有任何bean的类型和要注入的变量类型匹配,则报错。
    • 若IOC容器中有多个bean类型的对象和变量类型匹配,则按照注入的变量名为id查找key,有 责注入,无则报错。
  • 出现位置:可以是变量上,也可以是方法上。
  • 细节:使用注解注入时,set方法就不是必须的了。

spring

aaa@qq.com:

  • 作用:

    • 在按照类中注入的基础之上再按照名称注入,他在给类成员注入时不能单独使用,与 Autowired配合使用
  • 属性:

    • value:用于指定注入bean的id

aaa@qq.com:

  • 作用:
    • 直接按照bean的id注入,可以独立使用。
  • 属性:
    • name:用于指定bean的id

PS:

  • 以上三个注入只能注入其他bean类型的数据,而基本类型和String类型无法使用上述注解实现,集合类型的注入只能通过xml来实现

​ aaa@qq.com

​ 作用:用于注入基本类型和String类型的数据

​ 属性:value:用于指定数据的值,它可以使用spring中的spEL(spring的el表达式)

​ SpEL的写法:$(表达式)

3.用于改变作用域的范围

和xml中的bean标签中的属性标签实现的功能一致

aaa@qq.com

  • 作用:

    • 用于指定bean的作用范围
  • 属性:

    • value:用于指定范围的值,常用取值:singleton prototype

4.和生命周期相关

和xml中的bean标签中使用init-method和destroy-method属性实现的功能一致

1.PreDestroy

  • 作用:用于指定销毁方法

2.PostConstruct

  • 作用:用于指定初始化方法

5.新注解

1.Configuration

  • 作用:

    • 指定当前类是一个配置类
  • 细节:

    • 当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写

2.ComponentScan

  • 作用:

    • 用于通过注解指定Spring在创建容器时要扫描的包
  • 属性:

    • value:它和basePackages的作用是一样的,都是用于指定创建容器是要扫描的包。相当于在xml文件中开启注解。
<context:component-scan base-package="com.jsl"></context:component-scan>

3.Bean

  • 作用:

    • 用于把当前方法的返回值作为bean对象存入spring的IOC容器中
  • 属性:

    • name:用于指定bean的id,当不写时,默认值时当前方法的名称
  • 细节:

    • 当我们使用注解配置方法时,如果方法有参数,spring框架回去容器中查找有没有可用的 bean对象,查找方式和AutoWired注解的作用是一样的。

4.Import

  • 作用:

    • 用于导入其他配置类的字节码
  • 属性:

    • value:用于指定其他配置类的字节码
  • 当我们使用Import注解之后,有Import注解的为父配置类,被加进来的就是子配置类

5.PropertySource

  • 作用:

    • 用于指定properties文件的位置
  • 属性:

    • “classpath:properties文件名”

6.动态代理及实现方式

1)生活中代理场景的分析

spring

2)动态代理

  • 特点:字节码随用随创建,随用随加载。

  • 作用:不修改源码的基础上对方法增强

  • 分类:

    • 1.基于接口的动态代理:

      • 涉及的类:Proxy(JDK官方提供)

      • 创建代理对象:Proxy中的newProxyInstance()方法

      • 要求:被代理对象最少实现一个接口,如果没有则不能使用

      • newProxyInstance()参数:

        • ClassLoader:类加载器

          • 用于加载代理对象的字节码,和被代理对象使用相同的类加载器,固定写法
        • Class[ ]:字节码数组

          • 用于让代理对象和被代理对象有相同的方法,固定写法
        • InvocationHandler:用于提供增强的代码

让我们写代理。一般写一个实现该接口的实现类,通常为匿名类,不必须,谁用谁写。

  • 2.基于子类的动态代理

  • ​涉及的类:Enhancer(第三方cglib类库提供)

    • ​如何创建代理对象:使用Enhancer类中的create()方法
    • ​要求:被代理类不能是最终类
    • ​create()参数:
      • ​Class:字节码
        • ​用于指定代理对象的字节码
      • ​Callback:用于提供增强的代码
        • ​用于让代理对象和被代理对象有相同的方法,固定写法
      • ​InvocationHandler:用于提供增强的代码
  • ​让我们写代理。一般写一个实现该接口的实现类MethodInterceptor,通常为匿名类,不必须,谁用谁写。

事务控制
spring

7.AOP概念

Aspect Oriented Programming:面向切面编程

​ 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。对业务逻辑的各个部分进行隔离,从而使业务逻辑各部分之间的耦合度降低,提高代码重用性和开发效率。

作用:不修改源码,对已有方法进行增强

优势:减少重复代码,提高开发效率,容易维护

8.spring中的AOP相关术语

1)连接点Joinpoint:

将被增强还未增强的所有方法

2)切入点Pointcut:

被增强的方法

3)增强/通知类型

拦截到连接点之后要做的事情就是增强
spring

4)Introduction引介:

一种特殊的通知,不在修改类代码的前提下,在运行期间为类动态的添加一些方法或者Field。

5)Target目标对象

代理的目标对象

6)Weaving织入

是指把增强应用到目标对象来创建新的代理对象的过程。

​ spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入

7)Proxy代理

一个类被织入增强之后,产生一个结果代理类

8)Aspect切面

切入点和增强通知的结合

9. AOP要明确的事情

spring

spring中基于XML和注解的AOP配置

配置步骤:

1)将通知增强的bean交给spring管理

2)使用aop:config标签表明烤漆AOP的配置

3)使用aop:aspect标签表明配置切面

  • ​id属性:给切面提供一个唯一标识

  • ​ref属性:指定通知增强的bean的id

4)在aop:aspect标签内部使用对应标签配置通知的类型(五种增强方式)

前置通知:aop:before

  • ​method属性:用于指定前置通知的方法
  • ​pointcut属性:用于指定切入点的表达式,指的是对业务层中的那些方法进行通知增强

spring

环绕增强

spring
spring

5).切入点的表达式写法:

  • ​关键字:execution(表达式)

  • ​表达式:访问修饰符 返回值 包名.包名…类名.方法名.(参数列表)

    • ​标准写法:public void com.jsl.service.impl.CountImpl.saveCount( )

spring

全通配写法:

* *..*.*(..)

通常写法:切到业务层实现类下的所有方法

* com.jsl.service.impl.*.*(..)

通用化切入点表达式

spring

6)注解AOP

1.1在ioc中开启AOP注解

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

1.2不使用xml开启AOP注解

@Configuration
@ComponentScan(basePackages="com.jsl")
@EnableAspectJAutoProxy
public class SpringConfiguration{
}

2.在切面方法类上

@Aspect标注该类是一个切面类
public class Logger{
	@Pointcut("execution(* com.jsl.service.impl.*.*(..))")//切入点
	private void pt(){}
	@Before("pt()")//前置
	@AfterReturning("pt()")//后置
	@AfterThrowing("pt()")//异常
	@After("pt()")//最终
	@Around("pt()")//环绕
}

10.spring中的事务控制

1) XML配置

  • 1.配置事务管理器

  • 2.配置事务的通知

    • 导入事务tx的约束以及aop的约束

    • 使用tx:advice标签配置事务的通知/增强

    • 属性:

      • id:给事务通知起一个唯一标识

      • transaction-manager:给事务通知提供一个事务管理器引用

  • 3.配置AOP中通用的切入点表达式

  • 4.建立切入点表达式和事务通知的对应关系

  • 5.配置事务的属性

    • 在事务通知的tx:advice标签内部

spring

  • 6.开启事务注解的支持

spring

2) 注解配置

spring

spring

spring

相关标签: aop ioc