Spring概述
Spring起源
Spring框架最初是由Rod Johson编写的,并且2003年6月首次在Apache 2.0许可下发布。2004年Spring框架的第一版发布。
Spring框架是为了解决企业应用开发的复杂性问题而产生的。它为容易而快速的开发出耐用的Java应用程序提供了全面的基础设施。由于Spring是一个从实际开发中抽取出来的框架,因此它完成了大量开发中的通用步骤,留给开发者的仅仅是与特点应用相关的部分,使得开发者只需要关心业务需求,从而大大提高了企业应用的开发效率。
Spring实质
Spring是分层的轻量级开源框架,以IOC(Inverse of Control 控制反转)和AOP(Aspect Oriented Programming 面向切面编程)为内核,使用基本的JavaBean来完成以前只能由EJB完成的工作,取代了EJB的臃肿、低效的开发模式。 在实际开发中,通常服务器端采用三层体系架构,分别为表示层(web)、业务逻辑层(Service)和持久层(dao)。Spring对每一层都提供了技术支持。在表示层提供了与Structs2、Spring MVC等框架的整合;在业务层可以管理事务,记录日志等;在持久层可以整合MyBatis、Hibernate、JdbcTemplate等技术。如下所示:
因此,Spring提供了Java EE每一层的解决方案,所以可以说Spring是全栈的。
Spring优点
1.低侵入式设计,代码污染极低。 2.独立于各种应用服务器,基于Spring框架的应用,可以真正的实现Write Once,Run Anywhere。 3.Spring的IOC容器降低了业务对象替换的复杂性,提高了组件之间的解耦,提供了一种方法管理业务对象。 4.Spring的AOP支持允许将一些通用任务如安全、事务、日志等进行集中式管理,从而提高了更好的复用。 5.Spring的ORM和DAO提供了与第三方持久层框架的良好整合,并简化了底层的数据库访问。 6.Spring的高度开放性模块化,并不强制应用完全依赖于Spring,开发者自由选用Spring框架的全部或者部分。 7.方便程序测试:Spring的设计从底部帮助编写易于测试的代码。Spring对JUnit4支持,可以通过注解方便的测试Spring程序,是用于测试驱动工程的理想的framework 8.方便解耦、简化开发:Spring就是一个大工厂,可以将所有对象创建和依赖关系维护交给Spring管理。 9.AOP编程的支持:Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能 10.简单且强大的声明式事务管理的支持:只需要通过配置就可以完成对事务的管理,无序手动编程。 11.方便集成各种优秀框架:Spring内部通过了对各种优秀框架(如Struts2、Hibernate、MyBatista、Quartz等)的直接支持。 12.降低了JavaEE API的使用难度:对JavaEE开发中非常难用的一些API(如JDBC、JavaMail、远程调用等)都提供了封装,使这些API应用难度大大降低。
Spring框架的体系结构
Spring 总共大约有 20 个模块, 由 1300 多个不同的文件构成。 而这些组件被分别整合在如下6个模块集合中:
Core Container(核心容器)
AOP(Aspect Oriented Programming)
Instrmentation(设备支持)
Data Access/Integeration(数据访问及集成)
Web
Messaging(报文发送)
Test
下图是 Spring 5 的模块结构图
各个模块之间依赖关系如下图所示:
1.Core Container(核心容器)
核心容器层是其他模块建立的基础,由Core核心模块,Beans模块,Context上下文模块,和Spring Expression Language模块组成。
- Core核心模块
该模块提供了Spring框架的基本组成部分,包括IOC和依赖注入功能。
- Beans模块
该模块提供了BeanFactory,是工厂模式的经典实现。Spring将管理对象称为Bean。它移除了编码式单例的需要,并且可以把配置和依赖从实际编码逻辑中解耦。
- Context上下文模块
该模块是在Core和Beans模块的基础之上建立起来的,它是访问定义和配置任何对象的媒介。以一种类似于JNDI注册的方式访问对象。扩展了 BeanFactory, 为它添加了 Bean 生命周期控制、 框架事件体系以及资源加载透明化等功能。 此外该模块还提供了许多企业级支持, 如邮件访问、远程访问、 任务调度等。
ApplicationContext 是该模块的核心接口,它是 BeanFactory 的超类, 与BeanFactory 不同, ApplicationContext 容器实例化后会自动对所有的单实例 Bean 进行实例化与依赖关系的装配, 使之处于待用状态
。spring-context-support提供了对第三方库集成到Spring上下文的支持,比如缓存(EhCache, Guava, JCache)、邮件(JavaMail)、调度(CommonJ, Quartz)、模板引擎(FreeMarker, JasperReports, Velocity)等。
- Expression Language模块
该模块提供了强大的表达式语言,用于在运行时查询和操作对象图。
2.
Data Access/Integeration(数据访问/集成)
数据访问/集成层包括如下模块:
- JDBC(Java Data Base Connectivity)
该模块提供了JDBC抽象层,大幅度的减少了在开发过程中对数据库操作的代码,它消除了冗长的JDBC编码和对数据库供应商特定错误代码的解析。
- ORM(Object Relational Mapping)
该模块提供了对流行的对象关系映射API包括JPA,JDO和Hibernate等的集成。通过此模块可以让这些ORM框架和Spring的其他功能整合,比如前面提及的事务管理。
- OXM(Object XML Mapping)
该模块提供了对OXM实现的支持,比如JAXB、Castor、XML Beans、JiBx、XStream等。
- JMS(Java Message Service)
该模块指Java消息服务,包含生产和消费消息的功能。从Spring4.1开始,集成了Spring-messaging模块。
- Transaction(事务)处理模块。
该模块为实现特殊接口类及所有的POJO支持编程式和生命式事务管理。(注:编程式事务需要自己写beginTransaction()、commit()、rollback()等事务管理方法,声明式事务是通过注解或配置由spring自动处理,编程式事务粒度更细)
3.Web
Web层包括如下模块:
- Web
该模块提供了面向web的基本功能和面向web的应用上下文,比如多部分(multipart)文件上传功能、使用Servlet监听器初始化IoC容器等。它还包括HTTP客户端以及Spring远程调用中与web相关的部分。。
- Web-MVC
该模块为web应用提供了模型视图控制器(MVC)和REST Web服务的实现。Spring的MVC框架可以使得领域模型代码和web表单完全的分离,且可以与Spring框架的其他所有功能进行集成。
- Web-Socket
该模块为WebSocket-based提供了支持,而且在web应用程序中提供了客户端与服务端之间通信的两种方式。
- Web-Portlet
该模块提供了用于Portlet环境的MVC实现,并反映了Spring-webmvc模块的功能。
4.
AOP(Aspect Oriented Programming)
该模块提供了面向切面的编程实现。允许定义方法拦截器和切入点对代码进行干净的解耦,从而使实现功能的代码彻底的解耦出来。
5.Aspects
该模块提供了与AspectJ的集成,这是一个功能强大且成熟的面向切面编程(AOP)框架。
6.
Instrmentation(设备支持)
该模块在一定的应用服务器中提供了类instrumentation的支持和类加载器的实现。
7.Messaging
该模块为STOMP提供了支持作为在应用程序中WebSocket子协议的使用。
8.Test
该模块支持对具有JUnit或TestNG框架的Spring组件的测试。
Spring的下载及目录结构
Spring框架包
下载地址为:https://repo.spring.io/release/org/springframework/spring/,选择某个版本后,选择第一个下载,如下所示:
解压后的文件目录结构如下所示:
介绍如下:
docs文件夹 包含了Spring的API文档和开发规范 libs文件夹 包含开发需要的JAR包和源码 schema文件夹 包含开发所需要的schema文件,这些文件中定义了Spring相关配置文件的约束 打开libs文件夹后可以看到50多个JAR文件,如下所示:
可以看出,Spring的4个基础包分别对应Spring核心容器的4个模块,如下所示:
1.spring-beans-5.1.1.RELEASE.jar 2.spring-core-5.1.1.RELEASE.jar 3.spring-context-5.1.1.RELEASE.jar 4.spring-expression-5.1.1.RELEASE.jar 第三方依赖包
在使用Spring开发时,除了自带的JAR包外,还需要依赖第三方包commons.logging-版本号.jar。该JAR包主要用于处理日志,此JAR包可以去Apache官网下载。地址为:http://commons.apache.org/proper/commons-logging/download_logging.cgi。如下所示:
使用Spring框架时,只需要将Spring的4个基础包和commons-logging包复制到项目的lib目录,并发布到类路径即可。
使用Maven导入jar包
Bean
含义
被Spring IOC容器管理的对象称之为bean。
bean标签的属性
id bean的唯一标志
<bean id="beanExample"></bean>
class bean对应的类的全名(包名+类名)
<bean id="beanExample" class="day01.BeanExample"></bean>
init-method
初始化方法,在对象创建的时候就会调用该方法
<bean id="beanExample" class="day01.BeanExample" init-method="begin"></bean>
destroy-method
销毁方法,在容器关闭时调用该方法(只在单例模式下有效)
<bean id="beanExample" class="day01.BeanExample"destroy-method="end"></bean>
scope 值为singleton时表示单例模式
<bean id="beanExample" class="day01.BeanExample" scope="singleton"></bean>
值为prototype时表示非单例模式
<bean id="beanExample" class="day01.BeanExample" scope="prototype"></bean>
factory-method 调用的工厂方法
<beanid="beanExample" class="day01.BeanExample" factory-method="getInstance"></bean>
factory-bean 调用的工厂bean
<bean id="beanExample" class="day01.BeanExample" factory-bean="c2" ></bean>
lazy-init 值为true时表示使用getBean方法的时候,创建该对象。
<bean id="beanExample" class="day01.BeanExample" lazy-init="true"></bean>
值为false时表示创建容器的时候,创建容器中的该对象(默认值)
<bean id="beanExample" class="day01.BeanExample" lazy-init="false"></bean>
constructor-arg
用来注入依赖关系,调用有参构造方法,在创建对象时传入参数
<bean id="sdf" class="java.text.SimpleDateFormat">
<!-- 通过index匹配参数的内容:index表示对象参数的位置 value表示index位置对应的值 -->
<constructor-arg index="0" value="yyyy-MM-dd"></constructor-arg>
<!-- 通过参数名匹配参数的内容:index表示对象参数的位置 value表示index位置对应的值 -->
<constructor-arg name="date" value="yyyy-MM-dd"></constructor-arg>
</bean>
property set注入:调用无参构造方法,完成对象的创建,然后调用每个属性的set方法(必须要有set和get方法),完成属性值的初始化。
<bean id="setCom" class="day1.Computer">
<property name="hdd" value="金士顿"></property>
<property name="cpu" value="华为"></property>
<property name="mainboard" value="小米"></property>
</bean>
容器中实例化bean的方式
在容器中实例化bean的时候,id不能相同。
1.通过构造方法
2.通过工厂方法(静态方法)
3.通过一个对象的实例创建另一个对象(实例方法)
自动装配
autowire:自动查找到对应的属性对象,适用于set注入方式。
1.语法
<bean id="" class="" autowire="byName/byType"> ... </bean>
说明:
byName 根据set方法的名字和bean的名字进行一个自动匹配 byType 根据set方法的类型和bean的名字进行一个自动匹配
要求容器中,符号类型的bean只能出现一次
2.数据类型
可以通过<util>标签,配置list、set、map、properties等内容
注解
注解详情见https://blog.csdn.net/qq_35507234/article/details/102554625
spring组件自动扫描
定义
通过对javabean对象进行注解配置,然后可以直接使用这些bean对象,不再需要到配置文件中使用<bean>标签进行配置了。
开启组件自动扫描功能
<context:component-scan base-package="xxx"></context:component-scan> base-package:表示支持组件自动扫描的类在哪个包中(包含子包中所有的类)
注意事项
开启组件自动扫描之后,则表示支持使用注解,则开启注解的代码可以省略。省略如下代码:
<context:anotaion-config></context:anotation-config>
JUnit测试
1.传统的测试
如下所示:
缺点:
1.测试案例包含了Spring容器,每一次测试都需要创建新的Spring容器,测试完毕销毁Spring容器。性能开销大。 2.非正常的方式关闭SPring容器 2.Spring测试
如下所示:
3.Spring的JUnit4测试的使用
1)使用Maven导入jar包
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-test --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.1.8.RELEASE</version> <!-- <scope>test</scope> --> </dependency>
2)使用
- 给类加注解
//表示运行Spring的JUnit @RunWith(SpringJUnit4ClassRunner.class) //表示上下文配置对象(寻找指定的配置文件) @ContextConfiguration("classpath:xxx.xml")
- 给方法加注解
使用@Test。注意:方法没有参数,也没有返回值。
- 案例
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:day3-1.xml") public class JUnitTest { @Autowired private String name; @Autowired private Phone phone; @Test public void testName() { System.out.println(name); } @Test public void testPhone() { System.out.println(phone); } }
3.Spring的JUnit5测试的使用
在测试类上使用注解:@SpringJUnitConfig
Spring的AOP
概念
AOP(Aspect Orient Programming)即面向切面编程,是对OOP(Object Orient Programming)即面向对象编程的一种补充,专门用于处理一些具有横切性质的服务。比如将那些与业务无关,但却对多个对象产生影响的一些公共行为和逻辑进行抽取,并封装为一个可重用的模块,这个模块就被命名为切面(Aspect)。常常用于日志处理、安全控制、权限认证、事务处理等等。
允许定义方法拦截器和切入点对代码进行干净的解耦,从而使实现功能的代码彻底的解耦出来。关注点是共同处理,通过配置将其作用到一个或多个目标对象上。好处在于实现组件的重用、减少系统中的重复代码、改善程序的结构、提高灵活性。
Aspect(切面) 指共通的业务处理,可以切入到多个目标对象,可以多次使用。 Join Point(连接点) 指切面组件在目标对象上的一个作用位置 Pointcut(切入点) 切入点的连接点的集合,使用表达式指定。
如:expression="execution(* day3..*.*(..))"
依次按照顺序如下:
*:表示方法的返回是任意类型
day3..*:表示day3包及其子包
.*:表示任意方法名称
(..):表示任意参数类型和个数
Advice(通知) 指定是在切面的某个特定的连接点上要执行的动作。通知有各种类型,其中包括“around”、“before”和“after”等通知。 Target Object(目标对象) 被一个或多个切面所通知(advise)的对象 配置AOP
可以通过XML文件配置或者AspectJ注解的方式来声明横切逻辑起作用的位置来实现AOP
导入jar包
<!-- spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.5.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>1.8.9</version> </dependency>
①通过XML文件方式配置
<?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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> <!-- 开启组件自动扫描功能 --> <context:component-scan base-package="day3"></context:component-scan> <aop:config> <aop:aspect id="log" ref="logging"> <aop:pointcut expression="execution(* day3..*.*(..))" id="allMethod"/> <!-- 表示day3包中的所有方法执行之前,都要执行Logging类中的befroeMethod方法--> <aop:before method="beforeMethod" pointcut-ref="allMethod"/> <!-- 表示day3包中的所有方法执行之前,都要执行Logging类中的afterMethod方法, 且将方法的返回值传递给afterMethod方法作为参数 --> <aop:after-returning method="afterMethod" pointcut-ref="allMethod" returning="obj"/> <!-- 表示day3包中所有方法执行时抛出异常时,则会执行Logging类中的afterException方法, 且将方法抛出的异常传递给afterException方法作为其参数 --> <aop:after-throwing method="afterException" pointcut-ref="allMethod" throwing="e"/> </aop:aspect> </aop:config> </beans>
②使用AspectJ注解
AOP实现原理
AOP实现的关键在于代理模式,AOP代理模式主要分为静态代理和动态代理。静态代理的代表为AspectJ,动态代理的代表为Spring AOP。
静态代理 AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强,会在编译阶段将AspectJ(切面)切入到Java字节码中,运行时就是增强之后的AOP对象。 动态代理 AOP框架不会去修改字节码,而是在每次运行时,在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法 静态代理和动态代理的区别在于生成AOP代理对象的时机不同,相对于而言静态代理具有更好的性能,但是静态代理需要特定的编译器进行处理,而动态代理不需要。
Spring AOP
Spring AOP默认采用的是JDK动态代理,在代码运行期间对业务方法进行增强,不会生成新类。Spring AOP使用两种方式进行支持:JDK动态代理和CgLib(Code Generation Library)动态代理。
①JDK动态代理
JDK动态代理只能为接口创建动态代理实例,而不能对类进行动态代理。核心InvocationHandler接口类和Proxy类,InvocationHandler接口类通过invoke()方法反射来调用目标类中的方法,动态的将横切逻辑和业务编织在一起,接着Proxy类利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。
②CgLib动态代理
如果代理类没有实现InvocationHandler接口,那么Spring AOP会选择使用CgLib来动态代理目标类。CgLib是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定的方法并添加增强代码,从而实现AOP。CgLib是通过继承的方式实现动态代理,因此如果某个类被标记为final,那么无法使用CgLib。
CgLib动态代理需要依赖asm包,把被代理对象类的class文件加载进来,修改其字节码生成子类。
Spring的IOC
IOC概念
所谓的IOC(控制反转)就是指创建对象的控制权发生反转。在程序的设计中,实例对象不再由调用者来创建,而是由Spring容器来创建,Spring容器负责根据配置文件去创建实例和管理各个实例之间的依赖关系。这样调用者只管从容器中获取需要使用的实例对象,而不必关心实例对象的创建过程,也不必关系该实例对象依赖对象的创建以及依赖关系的组装,对象与对象之间松散耦合,利于功能的复用。如下所示:
- 控制
由IOC容器来控制对象的创建及销毁(生命周期)
- 反转
将对象的控制权交给IOC容器。
ICO容器
Spring提供了两种IOC容器,分别是BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口,Spring容器通过DI建立对象(组件、bean)之间的关系。
①BeanFactory
BeanFactory是Spring中最古老最底层的接口,表示Spring IOC容器生产bean对象的工厂,包含了各种Bean的定义、读取Bean的配置文件,管理Bean的加载、实例化、生命周期,维护Bean之间的依赖关系。被Spring IOC容器管理的对象称之为bean。
②ApplicationFactory
ApplicationFactory作为BeanFactory的子接口,除了提供BeanFactory所具有的所有功能外,还提供了更加完整的框架功能:
1.继承MessageSource,因此支持国际化 2.统一的资源文件访问方式 3.提供在监听器中注册Bean的事件 4.同时加载多个配置文件 5.载入多个(有继承关系)上下文,使得每一个上下文都专注于一个特定的层次,比如应用的web层。 ③两者区别
BeanFactory BeanFactory采用延迟加载形式来注入Bean,即在使用Bean(调用getBean())才会对该该Bean进行加载实例化。 ApplicationContext ApplicationContext会在容器启动时就会一次性加载创建了所有Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。
唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。
Tomcat中初始化容器
在Tomcat的web.xml配置文件中添加如下代码:
<!-- listener:加载spring容器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <!-- applicationcontext.xml表示为Spring的配置文件 --> <param-value>classpath:applicationcontext.xml</param-value> </context-param>
IOC容器如何管理bean
- 1.通过Resource对象加载配置文件
- 2.解析配置文件,得到指定名称的bean
- 3.解析bean元素,id作为bean的名字,class用于反射得到bean的实例。注意:此时bean类必须存在一个无参构造器(和访问权限无关)
- 调用getBean方法的时候,从容器中返回对象的实例
获取IOC容器中的实例Bean对象
两种方式:一种是基于注解的方式,一种是通过Spring容器的getBean方法
①注解方式
使用@Autowire方式
②通过Spring容器的getBean方法
通过如下方法:
<T> T getBean(String name, @Nullable Class<T> requiredType)
如下所示:
//1.获取Spring容器(Student初始化在容器中) ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); //2.获取容器中的StudentDao实例对象 //Student stu = ac.getBean("stu"); Student stu = ac.getBean("stu", Student.class);
Spring Bean的生命周期
实例化Bean,设置对象属性(依赖注入),处理Aware接口,BeanPostProcessor,InitializingBean和init-method,DisposableBean,destory-method
Spring Bean的作用域
Bean的作用域可分为5个范围:
singleton 默认的单例模式,容器中只有一个Bean实例,由BeanFactory来维护。 prototype 非单例的,会为每一个Bean请求创建一个实例 request 为每一个网络请求创建一个实例,在请求完成之后,Bean会是失效并被垃圾回收器回收。 session 与request类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。 global-session 全局作用域 Spring IOC实现原理
Spring IOC使用反射机制 + XML技术。
DI(依赖注入)
DI概念
DI(dependency injection),是IOC的一种实现。指在创建对象的过程中依赖IOC容器来动态注入对象所需要的外部资源。
DI注入方式
注入方式有三种:构造器注入、setter方法注入和注解注入。
①构造器
在XML配置文件中进行配置:
<!-- 调用无参构造方法 --> <bean id="computer1" class="day02.Computer"></bean> <!-- 调用有参构造方法:使用参数的下标匹配参数的内容 --> <bean id="computer2" class="day02.Computer"> <constructor-arg index="0" value="金士顿1"></constructor-arg> <constructor-arg index="1" value="华硕1"></constructor-arg> <constructor-arg index="2" value="英特尔1"></constructor-arg> </bean> <!-- 调用有参构造方法:使用参数名匹配参数内容 --> <bean id="computer3" class="day02.Computer"> <constructor-arg name="hdd" value="金士顿2"></constructor-arg> <constructor-arg name="mainBoard" value="华硕2"></constructor-arg> <constructor-arg name="cpu" value="英特尔2"></constructor-arg> </bean> <!-- 调用有参构造方法:使用参数类型匹配参数内容 --> <bean id="computer3" class="day02.Computer"> <constructor-arg type="int" value="001"></constructor-arg> <constructor-arg type="String" value="华硕2"></constructor-arg> </bean> <!-- 调用有参构造方法:还可以使用下标、参数名、参数类型结合一起使用来匹配 -->
②setter方法
在XML配置文件中进行配置:
<!-- 使用set注入来完成对象属性值的初始化,属性值一定要有set方法 --> <bean id="setComputer" class="day02.Computer"> <property name="hdd" value="金士顿3"></property> <property name="cpu" value="英特尔3"></property> <property name="mainBoard" value="华硕3"></property> </bean>
Spring容器会调用Computer类的setter方法进行赋值,如setHdd、setCpu和setMainBoard方法
底层实现的原理:使用反射技术。通过XML配置文件里面的name属性的值,通过反射就能找到指定的setter方法。
③注解
如下所示:
@Component 组件 @Controller 控制层组件 @Service 业务逻辑层组件 @Repository 数据持久访问层组件 @Configuration 表示配置bean Spring的自动装配
1.基于Spring的XML配置文件
no 默认的方式,不进行自动装配,通过手工设置ref属性来进行装配bean。。 byName 通过bean的id名称进行自动装配,如果一个bean的 property的name属性值与另一个bean 的id名称相同,就进行自动装配。 byType 根据参数的类型进行自动装配(注意:此种方式必须满足当前容器只有一个bean满足条件,存在两个或多个则会粗出错)。 constructor 利用构造函数进行装配,并且构造函数的参数通过byType进行装配,要求待装配的bean有相应的构造函数 autodetect 自动探测,如果有构造方法,通过 construct的方式自动装配,否则使用 byType的方式自动装配。 2.基于注解的方式
①@Autowired
@Autowired默认是按照类型byType装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。
使用@Autowired注解来自动装配指定的Bean,使用@Autowired注解之前需要在Spring配置文件中配置<context:annotation-config/>。在启动Spring IOC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IOC容器自动查找需要的bean,并装配给该对象的属性。
在使用@Autowired时,首先在容器中查询对应类型的bean:
1.如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据; 2.如果查询的结果不止一个,那么@Autowired会根据名称来查找; 3.如果上述查找的结果为空,那么会抛出异常。解决方法时,使用required=false。
②@Resource
@Resource默认按照名称byName来装配注入,只有当找不到与名称匹配的bean才会按照类型来装配注入。
Spring整合JDBC
导入jar包
spring-jdbc.jar、mysql.jar
<!-- mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.1.7.RELEASE</version> </dependency>
配置JdbcTemplate
<bean id="jdbc" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="ds"></property> </bean> <bean id="ds" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="username" value="root"></property> <property name="password" value="root"></property> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/mydb3?useUnicode=true; characterEncoding=utf-8&useSSL=false"></property> </bean>
Spring使用到的设计模式
工厂模式
BeanFactory是简单工厂模式的体现,用来创建对象的实例;
单例模式
Bean默认为单例模式
代理模式
Spring AOP用到了JDK的动态代理和CgLib
模板方法模式
用于解决代码重复的问题,比如.RestTemplate, JmsTemplate, JpaTemplate。
观察者模式
定义对象一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现--ApplicationListener。
Spring的事务
Spring事务的种类
Spring事务分为编程式事务和声明式事务
1.编程式事务
编程式事务管理使用TransactionTemplate
2.声明式事务
声明式事务管理简历在AOP之上。其本质是通过AOP功能,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法开始之前加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
3.两者区别
声明式事务最大的优点就是不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明或通过@Transactional注解的方式,便可以将事务规则应用到业务逻辑中。
不足地方是,声明式事务最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。
事务传播行为
事务传播(Propagation)行为:指的是当多个事务同时存在的时候,spring如何处理这些事务的行为。有如下传播行为:
PROPAGATION_REQUIRED 如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。 PROPAGATION_SUPPORTS 支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘ PROPAGATION_MANDATORY 支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。 PROPAGATION_REQUIRES_NEW 创建新事务,无论当前存不存在事务,都创建新事务。 PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。 PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。
Spring的通知类型
前置通知(Before Advice)
在连接点之前执行的Advice,不过除非它抛出异常,否则没有能力中断执行流。使用
@Before
注解使用这个Advice。返回后通知(After return Advice)
在连接点正常结束之后执行的Advice。例如,如果一个方法没有抛出异常正常返回。通过
@AfterReturning
关注使用它。抛出异常后通知(After throwing Advice)
如果一个方法通过抛出异常来退出的话,这个Advice就会被执行。通用
@AfterThrowing
注解来使用。后置通知(After Advice)
无论连接点是通过什么方式退出的(正常返回或者抛出异常)都会执行在结束后执行这些Advice。通过
@After
注解使用。环绕通知(Around Advice)
围绕连接点执行的Advice,就你一个方法调用。这是最强大的Advice。通过
@Around
注解使用。