Spring词义春天,意图给开发行业带来春天,它小巧且功能强大,提供了IoC控制反转与AOP等功能。现如今,Java开发又被戏称为Spring开发。
1、Spring
1.1、Spring资源
中文文档:https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference
github:https://github.com/spring-projects
maven:
1 | <!--在maven中导入webmvc会自动导入Spring其他依赖--> |
Spring学习路线:Spring Framework->Spring Mvc->Spring Boot->Spring Cloud
1.2、Spring介绍
- Spring是一个开源的免费的框架(容器)。
- Spring是一个轻量级的、非入侵式的框架。
- 控制反转(IoC),面向切面编程(AOP)。
- 支持事物的处理,对框架整合的支持。
1.3、Spring模块
Spring由七大模块组成(图片来源于官网)
2、IoC对象创建
2.1、IoC理论
IoC(Inversion of Control):控制反转。
DI(Dependency Injection):依赖注入,DI是IoC的一种实现。
IoC主要解决类之间的互相依赖导致的紧耦合。在面向对象程序设计中,随着功能的增添,程序越发庞大,对象与对象之间的依赖也越来越复杂,常常改一个地方,其他处也会随之出现问题。
注:图片来源于官网。
配置方式:
控制:谁来创建对象,传统应用程序的对象由程序本身创建,在Spring中,对象由Spring通过反射创建。
反转:程序本身不创建对象,变为被动接受对象。
依赖注入:使用Bean的set方法进行注入。
2.2、无参构造
Spring文件:
1 |
|
在xml文件中,id相当于对象名,class全限定类名,property属性
1 | ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); |
使用ClassPathXmlApplicationContext加载IoC容器。
一个IoC容器持有一个或多个bean。
2.3、有参构造
Spring对于有偿构造主要使用“constructor-arg”标签实现。
1、index
1 | <!--使用下标传递参数--> |
index从0开始,依次对构造函数依次赋值。
2、type
1 | <!--使用类型全名传递参数--> |
type使用类型的全限定名进行赋值,例,当重载构造方法时,构造方法的参数名相同类型不同,type可以很好的解决传参问题。
3、name
1 | <!--使用参数名称进行传参--> |
在构造方法中,构造方法没有重载,或构造方法的参数没有重名时使用。
2.4、重点
IoC容器在加载完成xml文件,对象在这时创建完成,在之后获取的对象都是同一对象,不需要重新创建。
3、Spring配置
3.1、alias别名
1 | <!--别名--> |
起别名之后俩个名称都可以获取到对象。
3.2、bean配置
1 | <bean id="setHello" class="com.jiuzhao73.pojo.Hello" name="sh,sHello"/> |
- id相当于对象名。
- class类名。
- name相当于别名,别名可以使用多个,用”,”或” “间隔。
3.3、import导入
import一般用于团队开发,他可以将多个配置文件合并,最后只需要读取这个文件就可以获取所有对象。
1 | <!--导入--> |
4、DI依赖注入
4.1、构造器注入
4.2、Set注入
注入类型:
1 | bean | ref | idref | list | set | map | props | value | null |
依赖注入:Set注入
依赖:bean对象的创建依赖于容器
注入:bean对象中的所有属性,由容器来注入
例子:
Teacher类:
1 | public class Teacher { |
Student类:
1 | public class Student { |
xml文件:
1 |
|
测试:
1 | public class DITest { |
结果:
4.3、扩展方式注入
其他注入方式:
- c命名空间:使用构造器赋值
- p命名空间:使用set注入
导入约束:
1 | <!--p命名空间--> |
1 | <!--c命名空间,使用构造函数--> |
4.4、作用域
1、singleton(单例模式)
bean对象的默认作用域为单例,但是也可以显示设置。如:
1 | <bean id="jiuzhao" class="com.jiuzhao73.pojo.User" scope="singleton"/> |
2、prototype(原型模式)
1 | <bean id="jiuzhao" class="com.jiuzhao73.pojo.User" scope="prototype"/> |
3、其他作用域
在web开发时使用:
- request
- session
- application
- websocket
5、bean的自动装配
5.1、自动装配
自动装配(autowire),即不需要手动注入,由Spring自动识别,注入属性对象等。
自动装配设置:在bean标签中的autowire属性
5.2、byName
1 | <bean id="pants" class="com.jiuzhao73.pojo.Pants"> |
byName会匹配对象名与set注入的名称一致的对象,进行自动装配,存在对象名不标准注入失败问题。
5.3、byType
1 | <bean id="root" class="com.jiuzhao73.pojo.People" autowire="byType"> |
byType需要属性类型一致,进行自动装配,存在单个bean文件类型只能出现一次问题。
5.4、注解装配
注释与xml孰优孰劣:
The short answer is “it depends.” The long answer is that each approach has its pros and cons, and, usually, it is up to the developer to decide which strategy suits them better.
官网大意:视情况而定。
注释更短、更简洁,xml擅长链接组件。
步骤:
- 导入注解约束:
1 | <beans xmlns="http://www.springframework.org/schema/beans" |
- 注解支持:
1 | <context:annotation-config/> |
@Autowire
1 |
|
@Autowire在属性上使用,标记自动装配,使用注解甚至不需要拥有set方法(使用反射),原理是byName与byType的整合(先对bean类型进行匹配,若有多个匹配的类型,在使用名称匹配)。
@Nullable注释给参数使用,不报空指针异常。
1 | public void setName( String name){this.name = name;} |
@Autowired(required = [false|true]):true默认,不允许为空;当为false时,标志该属性可为空。
@Qualifier(value = “”)指定自动装配的名称
1 |
|
@Resource(java原生注解)
1 |
|
6、Annotation开发
6.1、开启注解开发
注意:在Spring4之后,注解需导入spring-aop包。
1 |
|
6.2、@Component类
@Component
1 |
|
在web开发中,经常使用mvc三层架构进行分层,从而诞生出了与之对映的三个的衍生注解:
- dao层:@Repository
- service层:@Service
- controller层:@Controller
四个注解功能基本一致。
6.3、@Value属性
@Value:
1 |
|
6.4、@Scope作用域
1 |
- singleton
- prototype
- request
- session
- application
- websocket
6.5、自动装配
6.6、示例
使用:
1 |
|
使用@Component默认对象名为类名小写,更换对象名可对参数value赋值。
@Value负责给属性赋值。当@Value用在方法上时,相当于传递一个值给这个方法,不需要固定set名称。例:
1 | //@Value("root") |
也可以赋值成功!
关于xml与注解较好的使用方式:使用@Value进行属性注入,在xml对对象进行管理。
6.7、@ComponentScan扫描
1 |
|
scan过滤器:
1 |
|
excludeFilters,includeFilters过滤器
关闭过滤器:useDefaultFilters=false
6.8、@Import导入
@Import注释:
1 |
|
7、基于Java配置
官网:
The central artifacts in Spring’s new Java-configuration support are
@Configuration
-annotated classes and@Bean
-annotated methods.
7.1、@Configuration
源码:
1 |
|
@Configuration是一个用于类的@Component注释,由Spring容器托管,其主要目的是作为Bean定义的来源。
7.2、@Bean
源码:
1 |
|
@Bean主要用于方法,可设置名称(name与value基本等价),做创建作用。
7.3、AnnotationConfigApplicationContext
示例:
创建bean类
1 |
|
创建Config类
1 |
|
AnnotationConfigApplicationContext创建IoC容器
1 | public void test(){ |
完全不使用xml文件,AnnotationConfigApplicationContext便可构建IoC容器。
AnnotationConfigApplicationContext也可以接受普通的@Component类和使用JSR-330元数据注释的类。
7.4、扫描scan(String…)
AnnotationConfigApplicationContext.scan(String…)方法会扫描一个包,加载@Component类。
1 |
|
或者
在JavaConfig使用注解,扫描:
1 |
|
8、Proxy代理模式
代理模式,为其他对象提供一种代理以控制对这个对象的访问。
通俗的来讲,就是对俩个直接通讯的类进行解耦,使其依靠于第三方执行。
1、静态代理
由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。
2、动态代理
Java的动态代理比代理的思想更进一步,它可以动态地创建代理并动态处理对所代理方法的调用。
API文档:
每一个动态代理类都必须要实现InvocationHandler接口,并且每个代理类的实例都关联一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发由InvocationHandler这个接口的invoke()方法进行调用。
1 | public interface InvocationHandler { |
1 | public class Proxy implements java.io.Serializable { |
9、AOP
9.1、什么是AOP
Aspect Oriented Programming(面向切面编程),平时oop开发是纵向开发,aop是横向开发,也可以叫做事件开发。
SpringAOP术语:
- Aspect(切面 ): 横切关注点被模块化的特殊对象。
- 横切关注点:跨越应用程序多个模块的方法或功能。
- Join point(连接点):与切入点匹配的执行点。
- Advice(通知):切面必须完成的工作。即类的一个方法。
- Pointcut(切入点):切面通知执行的地点的定义。
- Target object(目标对象): 被通知(切面)的对象(目标对象)。
插入位置:
- Before advice(前置通知)
- After returning advice(返回通知)
- After throwing advice(异常抛出通知)
- After (finally) advice(后置通知)
- Around advice(环绕通知)
Spring4.0
正常情况:环绕前置=====@Before======目标方法执行=====环绕返回=====环绕最终=====@After=====@AfterReturning
异常情况:环绕前置=====@Before======目标方法执行=====环绕异常=====环绕最终=====@After=====@AfterThrowing
Spring5.28
正常情况:环绕前置=====@Before=====目标方法执行=====@AfterReturning=====@After=====环绕返回=====环绕最终
异常情况:环绕前置=====@Before=====目标方法执行=====@AfterThrowing=====@After=====环绕异常=====环绕最终
9.2、Spring中AOP实现
maven:
1 | <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> |
1、SpringAPI
实现接口:
1 | public interface AfterReturningAdvice extends AfterAdvice { |
依赖导入:
1 | xsi:schemaLocation="http://www.springframework.org/schema/beans |
配置aop:
1 | <bean id="log" class="com.jiuzhao73.demo1.pojo.Log"/> |
JavaAPI:
AroundAdvice
1 | public interface MethodInterceptor extends Interceptor { |
MethodBeforeAdvice
1 | public interface MethodBeforeAdvice extends BeforeAdvice { |
实现接口的before()方法,在方法之后调用。
AfterReturningAdvice
1 | public interface AfterReturningAdvice extends Advice { |
IntroductionInterceptor
1 | public interface IntroductionInterceptor extends MethodInterceptor { |
ThrowsAdvice
是个标签,在连接点抛出异常后调用引发通知。
1 | afterThrowing([Method, args, target], subclassOfThrowable) |
例:
1 | public class RemoteThrowsAdvice implements ThrowsAdvice { |
2、标签实现
1 | <bean id="aop" class="com.jiuzhao73.demo1.pojo.Aop"/> |
3、Annotation实现
在Spring中使用注解实现aop需开启注解自动代理,并注入被搜索类。
1 | <!--开启注解自动代理--> |
使用@Aspect注解
1 |
|
4、execution表达式
execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)
除了返回类型模式,方法名模式和参数模式外,其它项都是可选的。
例:
1 | execution(* com.jiuzhao73.demo1.pojo.Sell.*(..)) |
‘’*’’——>通配符(可能表示任意返回类型,某个包下的任意类,或任意包等等)
“..”——>表示任何参数类型
10、MyBatis-Spring
10.1、MyBatis与MyBatis-Spring
官网:http://mybatis.org/spring/zh/sqlsession.html
MyBatis框架:
Spring-MyBatis:
10.2、SqlSession
1、SqlSessionTemplate
DataSouce->SqlSessionFactoryBean->SqlSessionTemplate->mapper:
1 | <!--javax.sql.DataSource的实现--> |
UserMapperImpl类:
1 | public class UserMapperImpl implements UserMapper { |
2、SqlSessionDaoSupport
DataSouce->SqlSessionFactoryBean->UserMapperImpl2(SqlSessionDaoSupport子类):
1 | <!--前面两步与SqlSessionTemplate相同--> |
UserMapperImpl2类:
1 | public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper { |
SqlSessionDaoSupport类实现了getSqlSession()方法,因此我们可以很轻松的获取SqlSession不需要去设置属性。
10.3、事务
1、标准配置
开启 Spring 的事务处理功能,在 Spring 的配置文件中创建一个 DataSourceTransactionManager
对象:
1 | <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> |
Mybatis本身也有的两套事务管理器(type=”[JDBC|MANAGED]”),在使用Spring时我们则没有必要配置Mybatis的事务管理器。
2、声明式事务
导入tx:
1 | xmlns:tx="http://www.springframework.org/schema/tx |
在拥有DataSourceTransactionManager对象后,创建事务通知interceptor,对需要开启事务的方法设定为切入点,interceptor做为通知。
1 | <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> |
参考文献
尽管这不是一个详尽的清单,但还是希望对大家有所启示。
[1]Rod Johnson, Juergen Hoeller, Keith Donald, Colin Sampaleanu, Rob Harrop, Thomas Risberg, Alef Arendsen, Darren Davison, Dmitriy Kopylenko, Mark Pollack, Thierry Templier, Erwin Vervaet, Portia Tung, Ben Hale, Adrian Colyer, John Lewis, Costin Leau, Mark Fisher, Sam Brannen, Ramnivas Laddad, Arjen Poutsma, Chris Beams, Tareq Abedrabbo, Andy Clement, Dave Syer, Oliver Gierke, Rossen Stoyanchev, Phillip Webb, Rob Winch, Brian Clozel, Stephane Nicoll, Sebastien Deleuze, Jay Bryant, Mark Paluch.Spring官网文档[EB/OL]:2021