一、Spring框架介绍 1.Spring简介 Spring是2003年兴起的一个Java轻量级框架,它是为解决企业级开发的复杂性而创建的一个框架。 它是一个分层的JavaSE/EE Full-Stack(一站式)模型 Spring是一个容器,负责管理整个应用中所有Bean的生命周期及之间的依赖关系。 2.Spring和解耦合 Spring的作用就是为了解耦合,即降低代码间耦合度。 Spring将应用程序中的代码根据功能划分为两类:主业务逻辑与系统级服务 主业务逻辑代码的特点:具有很强的专业领域性,复用性相对较低,代码间耦合度相对较高。 系统级服务,也叫交叉业务逻辑。例如,事务管理,日志管理,安全管理等,其特点是,专业领域性不强,复用性高,代码间耦合程度相对较高,系统级服务,是为主业务逻辑服务的,它需要交叉(植入)到主业务逻辑 代码中。这样的话,主业务逻辑与交叉业务逻辑间的耦合度就比较高了。 Spring就是针对以上两种高耦合度代码,使用了Ioc和AOP两种技术降低它们的耦合度。 3.Spring特点 (1)、非嵌入式编程:POJO、Plain Old Java Object (2)、容器 (3)、IoC:Inversion of Control(控制反转) (4)、AOP:Aspect Oriented Programing(面向切面编程) 4.Spring框架jar包下载与目录结构 下载地址:https://repo.spring.io 5.Spring程序步骤 (1)、导入jar包
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.3.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.25</version>
</dependency>
(2)、创建Spring容器--配置文件 对程序员来说:Spring容器就是一个xml配置文件;对于java代码来说,Spring容器就是一个对象 这个对象,肯定是将这个xml配置文件加载到内存后,形成的对象。 (3)、从容器中获取Bean
二、Spring的两种实现技术
1.IoC
Inversion of Control(控制反转),将原来由代码操纵的对象控制权,交由第三方容器,即这种对象的依赖关系管理方式,称为IoC。 IoC是一种思想,有很多实现方式,比较出名的两种: (1)DL:Dependency Lookup(依赖查找),最典型的应用是JNDI,Java Naming and Directory Interface(Java 名称和目录接口) JNDI就是一种第三方容器。 (2)DI:Dependency Injection(依赖注入),目前最优秀的解耦方式,典型应用是Spring。 基于XML的DI: DI:依赖注入,就是为对象的属性赋值 1、设置注入 调用相关属性得setter方法完成赋值的过程。
<?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="mySchool" class="com.abc.di01.School">
<property name="sname" value="aynu"/>
</bean>
<bean id="student" class="com.abc.di01.Student">
<property name="name" value="张三"/>
<property name="age" value="23"/>
<property name="school" ref="mySchool"/>
</bean>
</beans>
2、构造器注入 调用相关构造器完成对象创建和属性赋值的过程。
<?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="mySchool" class="com.abc.di02.School">
<property name="sname" value="aynu"/>
</bean>
<bean id="student" class="com.abc.di02.Student">
<constructor-arg name="name" value="张三"/>
<constructor-arg name="age" value="23"/>
<constructor-arg name="school" ref="mySchool"/>
</bean>
<bean id="student1" class="com.abc.di02.Student">
<constructor-arg index="0" value="tom"/>
<constructor-arg index="1" value="18"/>
<constructor-arg index="2" ref="mySchool"/>
</bean>
<bean id="student2" class="com.abc.di02.Student">
<constructor-arg value="Mary"/>
<constructor-arg value="20"/>
<constructor-arg ref="mySchool"/>
</bean>
</beans>
3、命名空间注入 p命名空间,设置注入的另外一种写法 c命名空间,构造器注入的另外一种写法 了解即可 4、数组和集合注入
<?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="aynu" class="com.abc.di05.School">
<property name="sname" value="清华大学"/>
</bean>
<bean id="hnnu" class="com.abc.di05.School">
<property name="sname" value="北京大学"/>
</bean>
<bean id="some1" class="com.abc.di05.Some">
<property name="names" value="tome mary"/>
<property name="myList" value="henan anyang"/>
<property name="schools" ref="aynu"/>
<property name="mySet" value="软件工程,大数据"/>
<property name="myMap">
<map>
<entry key="phone" value="290101"/>
<entry key="qq" value="666888"/>
</map>
</property>
<property name="myPros">
<props>
<prop key="email">tom@163.com</prop>
<prop key="address">文明大道</prop>
</props>
</property>
</bean>
</beans>
5、域属性注入 byName:系统会从容器中查找与域属性同名的Bean,自动注入。 byType:系统会从容器中查找与域属性同类型的Bean,自动注入。 另外,系统会从容器中查找与域属性类型具有is-a关系的Bean,将其自动注入,与域属性类型具有is-a关系的Bean不能多于一个 6、SPEL注入 Spring Expression Language,Spring EL表达式
<?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="person" class="com.abc.di07.Person">
<property name="pname" value="张三"/>
<!-- <property name="page" value="23"/>-->
<property name="page" value="#{T(java.lang.Math).random()*50}"/>
</bean>
<bean id="student" class="com.abc.di07.Student">
<property name="name" value="#{person.pname}"/>
<!-- <property name="age" value="#{person.page>25?25:person.page}"/>-->
<property name="age" value="#{person.computeAge()}"/>
</bean>
</beans>
基于注解的DI 1、搭建环境 (1)、导入AOP的jar包
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.25</version>
</dependency>
(2)、配置文件添加Context约束 (3)、在配置文件中注册组件扫描器
<?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">
<!-- 注册组件扫描器,表示系统从com.abc.da01这个包及其子包中扫描组件-->
<context:component-scan base-package="com.abc.da01"/>
<!-- 注册组件扫描器,表示系统从com.abc.da01这个包的所有子包中扫描组件-->
<!-- <context:component-scan base-package="com.abc.da01.*"/>-->
</beans>
2、@Component 注解:表示当前类的对象由Spring容器来管理 与@Component功能相同,意义不同的注解,还有 @Service:注解Service类上 @Respository:注解在Dao类上 @Controller:注解在SpringMVC的处理器上 3、域属性的自动注入注解 (1)、byType @Autowired @Resource任选一种 (2)、byName 既可以@Autowired和@Qualifier同时使用,也可以只用@Resource(name = "") 4、其它注解 @Scope @PostConstruct @PreDestroy 5、注解注入:既不是设置注入,也不是构造器注入 6、注解与XML配置谁的优先级高? XML配置的优先级高,目的是便于后期项目的维护。
2.AOP
1、AOP简介 Aspect Orient Programming,面向切面编程,它是一种思想,实现者很多,Spring就是其中之一。 AOP是OOP的一种补充,OOP是从静态角度考虑程序的结构,而AOP是从动态角度考虑程序的运行过程。 Spring用于降低代码耦合度。IoC用于降低的是主业务逻辑之间的耦合度,AOP用于降低主业务逻辑与系统级服务(交叉业务逻辑)间的耦合度,将系统级服务在运行时织入到主业务逻辑之中。 Spring的AOP的底层工作原理,是使用动态代理对主业务进行增强。 2、AOP相关概念 (1)切面 切面就是交叉业务逻辑,就是要对主业务逻辑进行增强的部分。AOP中常见的切面有两种:通知、顾问。 (2)织入 将切面其切入到主业务逻辑中的过程。 (3)连接点 可以织入切面的目标类的目标方法。 (4)切入点 真正织入切面的目标类的目标方法。切入点一定是连接点,连接点未必是切入点。 (5)目标对象 目标类创建的对象就是目标对象。 主业务逻辑所在的类的对象是目标对象。 用于被增强的对象是目标对象。 (6)通知(Advice) 是一种切面,可以完成简单的植入功能。 3、AspectJ对AOP的实现 1)AspectJ概述 (1)AspectJ是什么? AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,有一个专门的编译器用来生成遵守Java字节编码规范的Class文件 (2)AspectJ、Spring与AOP的关系 AspectJ、Spring都是AOP的实现框架。AspectJ和Spring没有任何关系。 基于Spring环境下的AspectJ对AOP的实现 (3)AspectJ的通知类型 前置通知 后置通知 环绕通知 异常通知 最终通知 (4)搭建AspectJ编程环境 (1)导入jar包 除了Spring的基本jar包,还需四个jar包; AspectJ的核心包、Spring与AspectJ的整合包、AOP联盟的包、Spring对AOP7的实现包
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.19</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>6.0.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
(2)引入AOP的约束 (3)注册自动代理生成器
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 注册目标对象-->
<bean id="someService" class="com.abc.aop01.SomeServiceImpl"/>
<!-- 注册切面-->
<bean id="myAspect" class="com.abc.aop01.MyAspect"/>
<!-- 注册Aspect自动代理生成器-->
<aop:aspectj-autoproxy/>
</beans>
(5)切入点表达式 用于指定切入点。 execution(访问权限 返回值类型 全限定类名(接口名) 方法名(参数列表) 抛出异常) 例如: execution(* com.abc.service.*.*(..)):表示com.abc.service包下的所有方法都是切入点。 execution(* com.abc.service.*.open*(..)):表示com.abc.service包下的所有以open开头的方法都是切入点。 execution(* *.service.*.*(..)):表示service包下的所有方法都是切入点。 com.abc.service.ISomeService.doFirst()不是切入点,而com.service.ISomeService.doFirst()是切入点。 execution(* *..service.*.*(..)):表示service包下的所有方法都是切入点。 com.abc.service.ISomeService.doFirst()是切入点,而com.service.ISomeService.doFirst()也是切入点。 3、为应用指定多个Spring配置文件 (1)、并列关系,加载配置文件可以采用可变参数、数组、通配符。 (2)、包含关系,加载主配置文件,主配置文件包含其他配置文件。