前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring入门指南

Spring入门指南

原创
作者头像
ruochen
修改2021-11-23 13:18:04
8890
修改2021-11-23 13:18:04
举报

1.1.优点

  1. 方便解耦,简化开发

Spring就是一个大工厂,可以将所有对象的创建和依赖关系的维护,交给Spring管理。

  1. AOP编程的支持

Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能。

  1. 声明式事务的支持

只需要通过配置就可以完成对事务的管理,而无需手动编程。

  1. 方便程序的测试

Spring对Junit4支持,可以通过注解方便的测试Spring程序。

  1. 方便集成各种优秀框架

Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架的直接支持(如:Struts、Hibernate、MyBatis等)。

  1. 降低JavaEE API的使用难度

Spring对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低。

1.2.缺点

  1. Spring明明一个很轻量级的框架,却给人感觉大而全
  2. Spring依赖反射,反射影响性能
  3. 使用门槛升高,入门Spring需要较长时间

1.3.Spring框架的组成结构图

Spring 总共大约有 20 个模块, 由 1300 多个不同的文件构成。 而这些组件被分别整合在核心容器(Core Container) 、

AOP(Aspect Oriented Programming)和设备支持(Instrmentation) 、数据访问与集成(Data

Access/Integeration) 、 Web、 消息(Messaging) 、 Test等 6 个模块中。 以下是 Spring 5 的模块结构图:

组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:

1.3.1.核心容器

Spring的核心容器是其他模块建立的基础,有spring-core、spring-beans、spring-context、spring-context-

support和spring-expression(Spring表达式语言)等模块组成。

spring-core 模块 :提供了框架的基本组成部分,包括控制反转(Inversion of

Control,IOC)和依赖注入(Dependency Injection,DI)功能。

spring-beans 模块 :提供了BeanFactory,是工厂模式的一个经典实现,Spring将管理对象称为Bean。

spring-context 模块

:建立在Core和Beans模块的基础之上,提供一个框架式的对象访问方式,是访问定义和配置的任何对象的媒介。ApplicationContext接口是Context模块的焦点。

spring-context-support 模块

:支持整合第三方库到Spring应用程序上下文,特别是用于高速缓存(EhCache、JCache)和任务调度(CommonJ、Quartz)的支持。

Spring-expression 模块

:提供了强大的表达式语言去支持运行时查询和操作对象图。这是对JSP2.1规范中规定的统一表达式语言(Unified

EL)的扩展。该语言支持设置和获取属性值、属性分配、方法调用、访问数组、集合和索引器的内容、逻辑和算术运算、变量命名以及从Spring的IOC容器中以名称检索对象。它还支持列表投影、选择以及常用的列表聚合。

1.3.2.AOP 和设备支持

由spring-aop、 spring-aspects 和 spring-instrument等 3 个模块组成。

spring-aop 模块 :是 Spring 的另一个核心模块,提供了一个符合 AOP 要求的面向切面的编程实现。 作为继 OOP(面向对象编程)

后, 对程序员影响最大的编程思想之一, AOP 极大地开拓了人们对于编程的思路。 在 Spring 中,

以动态代理技术为基础,允许定义方法拦截器和切入点,将代码按照功能进行分离,以便干净地解耦。

spring-aspects 模块 :提供了与AspectJ的集成功能,AspectJ是一个功能强大且成熟的AOP框架。

spring-instrument 模块 :是 AOP 的一个支援模块,

提供了类植入(Instrumentation)支持和类加载器的实现,可以在特定的应用服务器中使用。主要作用是在 JVM 启用时, 生成一个代理类,

程序员通过代理类在运行时修改类的字节, 从而改变一个类的功能, 实现 AOP 的功能。

1.3.3.数据访问与集成

由 spring-jdbc、spring-orm、spring-oxm、spring-jms 和 spring-tx 等 5 个模块组成。

spring-jdbc 模块 :提供了一个JDBC的抽象层,消除了烦琐的JDBC编码和数据库厂商特有的错误代码解析, 用于简化JDBC。主要是提供

JDBC 模板方式、 关系数据库对象化方式、 SimpleJdbc 方式、 事务管理来简化 JDBC 编程, 主要实现类是 JdbcTemplate、

SimpleJdbcTemplate 以及 NamedParameterJdbcTemplate。

spring-orm 模块 :是 ORM 框架支持模块, 主要集成 Hibernate, Java Persistence API (JPA)

和Java Data Objects (JDO) 用于资源管理、 数据访问对象(DAO)的实现和事务策略。

spring-oxm 模块 :主要提供一个抽象层以支撑 OXM(OXM 是 Object-to-XML-Mapping 的缩写, 它是一个

O/M-mapper, 将 java 对象映射成 XML 数据, 或者将 XML 数据映射成 java 对象) , 例如:

JAXB,Castor,XMLBeans,JiBX 和 XStream 等。

spring-jms模块(Java Messaging Service)

:指Java消息传递服务,包含用于生产和使用消息的功能。自Spring4.1以后,提供了与spring-messaging模块的集成。

spring-tx 模块 :事务模块,支持用于实现特殊接口和所有POJO(普通Java对象)类的编程和声明式事务管理。

1.3.4.Web

由spring-websocket、spring-webmvc、spring-web、portlet和spring-webflux模块等 5 个模块组成。

spring-websocket 模块

:Spring4.0以后新增的模块,实现双工异步通讯协议,实现了WebSocket和SocketJS,提供Socket通信和web端的推送功能。

spring-webmvc 模块 :也称为Web-Servlet模块,包含用于web应用程序的Spring MVC和REST Web

Services实现。Spring MVC框架提供了领域模型代码和Web表单之间的清晰分离,并与Spring Framework的所有其他功能集成。

spring-web 模块

:提供了基本的Web开发集成功能,包括使用Servlet监听器初始化一个IOC容器以及Web应用上下文,自动载入WebApplicationContext特性的类,Struts集成类、文件上传的支持类、Filter类和大量辅助工具类。

portlet 模块 :实现web模块功能的聚合,类似于Servlet模块的功能,提供了Portlet环境下的MVC实现。

spring-webflux 模块 :是一个新的非堵塞函数式 Reactive Web 框架, 可以用来建立异步的, 非阻塞,事件驱动的服务,

并且扩展性非常好。

1.3.5.消息(Messaging)

即 spring-messaging 模块。

spring-messaging 是从 Spring4 开始新加入的一个模块, 该模块提供了对消息传递体系结构和协议的支持。

1.3.6.Test

即 spring-test 模块。

spring-test 模块 主要为测试提供支持的,支持使用JUnit或TestNG对Spring组件进行单元测试和集成测试。

2.Spring核心ioc

Ioc—Inversion of

Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。就是不实例化了。先注入。

谁控制谁,控制什么: 传统Java

SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由 Ioc容器

来控制对象的创建;谁控制谁?当然是 IoC 容器控制了对象 ;控制什么?那就是 主要控制了外部资源获取

为何是反转,哪些方面反转了:

有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

ps:控制反转是目标,依赖注入是手段。

2.1.ioc容器

IoC 容器是 Spring 的核心,也可以称为 Spring 容器。Spring 通过 IoC

容器来管理对象的实例化和初始化,以及对象从创建到销毁的整个生命周期。

Spring 中使用的对象都由 IoC 容器管理,不需要我们手动使用 new 运算符创建对象。由 IoC 容器管理的对象称为 Spring

Bean,Spring Bean 就是 Java 对象,和使用 new 运算符创建的对象没有区别。

Spring 通过读取 XML 或 Java 注解中的信息来获取哪些对象需要实例化。

Spring 提供 2 种不同类型的 IoC 容器,即 BeanFactory 和 ApplicationContext 容器

2.1.BeanFactory 容器

BeanFactory 是最简单的容器,由 org.springframework.beans.factory.BeanFactory

接口定义,采用懒加载(lazy-load),所以容器启动比较快。BeanFactory 提供了容器最基本的功能。

为了能够兼容 Spring 集成的第三方框架(如

BeanFactoryAware、InitializingBean、DisposableBean),所以目前仍然保留了该接口。

简单来说,BeanFactory 就是一个管理 Bean 的工厂,它主要负责初始化各种 Bean,并调用它们的生命周期方法。

BeanFactory 接口有多个实现类,最常见的是

org.springframework.beans.factory.xml.XmlBeanFactory。使用 BeanFactory 需要创建

XmlBeanFactory 类的实例,通过 XmlBeanFactory 类的构造函数来传递 Resource 对象。如下所示。

代码语言:txt
复制
Resource resource = new ClassPathResource("applicationContext.xml");
代码语言:txt
复制
BeanFactory factory = new XmlBeanFactory(resource);  

2.1.2. ApplicationContext 容器

ApplicationContext 继承了 BeanFactory 接口,由

org.springframework.context.ApplicationContext

接口定义,对象在启动容器时加载。ApplicationContext 在 BeanFactory 的基础上增加了很多企业级功能,例如

AOP、国际化、事件支持等。

ApplicationContext 接口有两个常用的实现类,具体如下。

2.1.2.1.ClassPathXmlApplicationContext

该类从类路径 ClassPath 中寻找指定的 XML 配置文件,并完成 ApplicationContext 的实例化工作,具体如下所示。

代码语言:txt
复制
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(String configLocation);

在上述代码中,configLocation 参数用于指定 Spring 配置文件的名称和位置,如 Beans.xml。

2.1.2.2.FileSystemXmlApplicationContext

该类从指定的文件系统路径中寻找指定的 XML 配置文件,并完成 ApplicationContext 的实例化工作,具体如下所示。

代码语言:txt
复制
ApplicationContext applicationContext = new FileSystemXmlApplicationContext(String configLocation);

它与 ClassPathXmlApplicationContext 的区别是:在读取 Spring

的配置文件时,FileSystemXmlApplicationContext 不会从类路径中读取配置文件,而是通过参数指定配置文件的位置。即

FileSystemXmlApplicationContext 可以获取类路径之外的资源,如“F:/workspaces/Beans.xml”。

2.1.2.3.AnnotationConfigApplicationContext

读取用注解创建容器

通常在 Java 项目中,会采用 ClassPathXmlApplicationContext 类实例化 ApplicationContext

容器的方式,而在 Web 项目中,ApplicationContext 容器的实例化工作会交由 Web 服务器完成。Web 服务器实例化

ApplicationContext 容器通常使用基于 ContextLoaderListener 实现的方式,它只需要在 web.xml 中添加如下代码:

代码语言:txt
复制
<!--指定Spring配置文件的位置,有多个配置文件时,以逗号分隔-->
代码语言:txt
复制
<context-param>
代码语言:txt
复制
    <param-name>contextConfigLocation</param-name>
代码语言:txt
复制
    <!--spring将加载spring目录下的applicationContext.xml文件-->
代码语言:txt
复制
    <param-value>
代码语言:txt
复制
        classpath:spring/applicationContext.xml
代码语言:txt
复制
    </param-value>
代码语言:txt
复制
</context-param>
代码语言:txt
复制
<!--指定以ContextLoaderListener方式启动Spring容器-->
代码语言:txt
复制
<listener>
代码语言:txt
复制
    <listener-class>
代码语言:txt
复制
        org.springframework.web.context.ContextLoaderListener
代码语言:txt
复制
    </listener-class>
代码语言:txt
复制
</listener>

需要注意的是,BeanFactory 和 ApplicationContext 都是通过 XML 配置文件加载 Bean 的。

二者的主要区别在于,如果 Bean 的某一个属性没有注入,使用 BeanFacotry 加载后,第一次调用 getBean() 方法时会抛出异常,而

ApplicationContext 则会在初始化时自检,这样有利于检查所依赖的属性是否注入。

因此,在实际开发中,通常都选择使用 ApplicationContext,只有在系统资源较少时,才考虑使用 BeanFactory。

2.2.使用ioc容器

2.2.1.beans.xml

代码语言:txt
复制
<?xml version="1.0" encoding="UTF-8"?>
代码语言:txt
复制
<beans xmlns="http://www.springframework.org/schema/beans"
代码语言:txt
复制
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xsi:schemaLocation="http://www.springframework.org/schema/beans      http://www.springframework.org/schema/beans/spring-beans.xsd">
代码语言:txt
复制
    <bean id="user" class="com.wyl.pojo.User">
代码语言:txt
复制
        <property name="name" value="王延领"/>
代码语言:txt
复制
    </bean>
代码语言:txt
复制
</beans>

2.2.2.pojo.User

代码语言:txt
复制
public class User { 
代码语言:txt
复制
    private String name; 
代码语言:txt
复制
    public User() {
代码语言:txt
复制
        System.out.println("user无参构造方法");
代码语言:txt
复制
    } 
代码语言:txt
复制
    public void setName(String name) {
代码语言:txt
复制
        this.name = name;
代码语言:txt
复制
    } 
代码语言:txt
复制
    public void show(){
代码语言:txt
复制
        System.out.println("name="+ name );
代码语言:txt
复制
    }
代码语言:txt
复制
}

2.2.2.test

代码语言:txt
复制
@Test
代码语言:txt
复制
public void test(){
代码语言:txt
复制
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
代码语言:txt
复制
    //在执行getBean的时候, user已经创建好了 , 通过无参构造
代码语言:txt
复制
    User user = (User) context.getBean("user");
代码语言:txt
复制
    //调用对象的方法 .
代码语言:txt
复制
    user.show();
代码语言:txt
复制
}

2.3.bean

2.3.1.定义

由 Spring IoC 容器管理的对象称为 Bean,Bean 根据 Spring 配置文件中的信息创建。可以把 Spring IoC

容器看作是一个大工厂,Bean 相当于工厂的产品,如果希望这个大工厂生产和管理 Bean,则需要告诉容器需要哪些 Bean,以及需要哪种方式装配 Bean。

Spring 配置文件支持两种格式,即 XML 文件格式和 Properties 文件格式。

  • Properties 配置文件主要以 key-value 键值对的形式存在,只能赋值,不能进行其他操作,适用于简单的属性配置。
  • XML 配置文件是树形结构,相对于 Properties 文件来说更加灵活。XML 配置文件结构清晰,但是内容比较繁琐,适用于大型复杂的项目。

通常情况下,Spring 的配置文件使用 XML 格式。XML 配置文件的根元素是 <beans style="margin: 0px; padding:

0px;">,该元素包含了多个子元素 <bean style="margin: 0px; padding: 0px;">。每一个 <bean

style="margin: 0px; padding: 0px;">元素都定义了一个 Bean,并描述了该 Bean 如何被装配到 Spring

容器中。</bean></bean></beans>

2.3.2.创建

2.3.2.1 默认方式

无参

代码语言:txt
复制
<!-- 1\. 默认构造函数,如果类中没有默认构造函数则无法创建对象;bean标签中只有id和class就默认使用构造函数创建对象 -->
代码语言:txt
复制
<bean id="userService" class="com.wyl.pojo.User"/>

有参

代码语言:txt
复制
<!-- 第一种根据index参数下标设置 -->
代码语言:txt
复制
<bean id="userService" class="com.wyl.pojo.User">
代码语言:txt
复制
    <!-- index指构造方法 , 下标从0开始 -->
代码语言:txt
复制
    <constructor-arg index="0" value="wyl"/>
代码语言:txt
复制
</bean>
代码语言:txt
复制
<!-- 第二种根据参数名字设置 -->
代码语言:txt
复制
<bean id="userService" class="com.wyl.pojo.User">
代码语言:txt
复制
    <!-- name指参数名 -->
代码语言:txt
复制
    <constructor-arg name="name" value="wyl"/>
代码语言:txt
复制
</bean>
代码语言:txt
复制
<!-- 第三种根据参数类型设置 -->
代码语言:txt
复制
<bean id="userService" class="com.wyl.pojo.User">
代码语言:txt
复制
    <constructor-arg type="java.lang.String" value="wyl"/>
代码语言:txt
复制
</bean>
2.3.2.2 工厂类中的方法
代码语言:txt
复制
<!-- 2\. 使用工厂中的方法创建对象;工厂中有一个方法可以创建对象,先创建工厂对象,通过factory-bean指向工厂,使用factory-method方法获取对象 -->
代码语言:txt
复制
<bean id="beanFactory" class="org.factory.BeanFactory"/>
代码语言:txt
复制
<bean id="userService" factory-bean="beanFactory" factory-method="getUserService"/>
2.3.2.3 静态工厂中的静态方法
代码语言:txt
复制
<!-- 3\. 使用静态工厂中的静态方法创建对象 -->
代码语言:txt
复制
<bean id="userService" class="org.factory.StaticBeanFactory" factory-method="getUserService"/>

2.3.2.配置

2.3.2.1.别名
代码语言:txt
复制
<!--  别名 : 如果添加了别名,我们也可以使用别名获取到这个对象 -->
代码语言:txt
复制
<alias name="User" alias="u1"></alias>
2.3.2.2.bean 别名
代码语言:txt
复制
<!--
代码语言:txt
复制
  bean标签常用属性:
代码语言:txt
复制
id属性:起名称,id属性值名称任意命名,不能包含特殊符号
代码语言:txt
复制
class属性:创建对象所在类的全路径
代码语言:txt
复制
name属性:功能和id属性一样的,但是在name属性值里面可以包含特殊符号
代码语言:txt
复制
scope属性
代码语言:txt
复制
singleton:默认值,单例
代码语言:txt
复制
prototype:多例
代码语言:txt
复制
request:创建对象把对象放到request域里面
代码语言:txt
复制
session:创建对象把对象放到session域里面
代码语言:txt
复制
globalSession:创建对象把对象放到globalSession里面
代码语言:txt
复制
  -->
代码语言:txt
复制
<bean id="UserT" class="com.wyl.pojo.User" scope="singleton" name="u2 u21,u22;u23">
代码语言:txt
复制
    <property name="name" value="123"/>
代码语言:txt
复制
</bean>
2.3.2.2.import

团队的合作通过import来实现 .

代码语言:txt
复制
<import resource="beans.xml"/>

能将多个人开发的不同的配置xml文件整合到applicationContext.xml文件中,并且能够合适的去重。

2.3.3.作用域

代码语言:txt
复制
<bean id="..." class="..." scope="singleton"/>

Spring 容器在初始化一个 Bean 实例时,同时会指定该实例的作用域。Spring 5 支持以下 6 种作用域。

singleton

默认值,单例模式 ,表示在 Spring 容器中只有一个 Bean 实例,Bean 以单例的方式存在。

prototype

原型模式,表示每次通过 Spring 容器获取 Bean 时,容器都会创建一个 Bean 实例。

request

每次 HTTP 请求,容器都会创建一个 Bean 实例。该作用域只在当前 HTTP Request 内有效。

session

同一个 HTTP Session 共享一个 Bean 实例,不同的 Session 使用不同的 Bean 实例。该作用域仅在当前 HTTP Session

内有效。

application

同一个 Web 应用共享一个 Bean 实例,该作用域在当前 ServletContext 内有效。

类似于 singleton,不同的是,singleton 表示每个 IoC 容器中仅有一个 Bean 实例,而同一个 Web 应用中可能会有多个 IoC

容器,但一个 Web 应用只会有一个 ServletContext,也可以说 application 才是 Web 应用中货真价实的单例模式。

websocket

websocket 的作用域是 WebSocket ,即在整个 WebSocket 中有效

**equest、session、application、websocket 和 global Session 作用域只能在 Web 环境下使用,如果使用

ClassPathXmlApplicationContext 加载这些作用域中的任意一个的 Bean,就会抛出以下异常。**

2.3.4.生命周期

Bean的生命周期

  1. Spring 启动,查找并加载需要被 Spring 管理的 Bean,并实例化 Bean。
  2. 利用依赖注入完成 Bean 中所有属性值的配置注入。
  3. 如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值。
  4. 如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用。
  5. 如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用。
  6. 如果 Bean 实现了 BeanPostProcessor 接口,则 Spring 调用该接口的预初始化方法 postProcessBeforeInitialzation() 对 Bean 进行加工操作,此处非常重要,Spring 的 AOP 就是利用它实现的。
  7. 如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 方法。
  8. 如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。
  9. 如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化方法 postProcessAfterInitialization()。此时,Bean 已经可以被应用系统使用了。
  10. 如果在 <bean style="margin: 0px; padding: 0px;">中指定了该 Bean 的作用域为 singleton,则将该 Bean 放入 Spring IoC 的缓存池中,触发 Spring 对该 Bean 的生命周期管理; 如果在 <bean style="margin: 0px; padding: 0px;">中指定了该 Bean 的作用域为 prototype,则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean。</bean></bean>
  11. 如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 方法销毁 Bean;如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方法对 Bean 进行销毁。
2.3.4.1.单例
代码语言:txt
复制
public class UserBean {
代码语言:txt
复制
    private String name;  
代码语言:txt
复制
    public UserBean(){  
代码语言:txt
复制
        System.out.println("UserBean()构造函数");  
代码语言:txt
复制
    }  
代码语言:txt
复制
    public String getName() {  
代码语言:txt
复制
        return name;  
代码语言:txt
复制
    }  
代码语言:txt
复制
    public void setName(String name) {  
代码语言:txt
复制
        System.out.println("setName()");  
代码语言:txt
复制
        this.name = name;  
代码语言:txt
复制
    }  
代码语言:txt
复制
    public void init(){  
代码语言:txt
复制
        System.out.println("this is init of UserBean");  
代码语言:txt
复制
    }  
代码语言:txt
复制
    public void destory(){  
代码语言:txt
复制
        System.out.println("this is destory of UserBean " + this);  
代码语言:txt
复制
    }  
代码语言:txt
复制
}
代码语言:txt
复制
<bean id="user_singleton" class="com.wyl.userBean" scope="singleton" 
代码语言:txt
复制
            init-method="init" destroy-method="destory" lazy-init="true"/>

当scope="singleton",即默认情况下,会在启动容器时(即实例化容器时)时实例化。但我们可以指定Bean节点的lazy-

init="true"来延迟初始化bean,这时候,只有在第一次获取bean时才会初始化bean,即第一次请求该bean时才初始化.

如果想对所有的默认单例bean都应用延迟初始化,可以在根节点beans设置default-lazy-init属性为true,如下所示:

代码语言:txt
复制
<beans default-lazy-init="true">
代码语言:txt
复制
public class LifeTest {
代码语言:txt
复制
    @Test 
代码语言:txt
复制
    public void test() {
代码语言:txt
复制
        AbstractApplicationContext container = 
代码语言:txt
复制
        new ClassPathXmlApplicationContext("user.xml");
代码语言:txt
复制
        UserBean user = (UserBean)container.getBean("user_singleton");
代码语言:txt
复制
        System.out.println(user);
代码语言:txt
复制
        container.close();
代码语言:txt
复制
    }
代码语言:txt
复制
}

UserBean()构造函数undefined this is init of UserBeanundefined com.wyl.UserBean@573f2bb1undefined ……undefined this is destory of UserBeancom.wyl.UserBean@573f2bb1

默认情况下,Spring在读取xml文件的时候,就会创建对象。在创建对象的时候先调用构造器[ UserBean() ,然后调用init-

method属性值中所指定的方法。对象在被销毁的时候,会调用destroy-method属性值中所指定的方法.

2.3.4.2.非单例管理的对象

当scope="prototype"时,容器也会延迟初始化bean,Spring读取xml文件的时候,并不会立刻创建对象,而是在第一次请求该bean时才初始化(如调用getBean方法时)。

在第一次请求每一个prototype的bean时,Spring容器都会调用其构造器创建这个对象,然后调用init-

method属性值中所指定的方法。对象销毁的时候,Spring容器不会帮我们调用任何方法,因为是非单例,这个类型的对象有很多个,Spring容器一旦把这个对象交给你之后,就不再管理这个对象了。

代码语言:txt
复制
<bean id="user_prototype" class="com.bean.UserBean" scope="prototype" init-method="init" destroy-method="destroy"/>
代码语言:txt
复制
public class UserTest {
代码语言:txt
复制
    @Test 
代码语言:txt
复制
    public void test() {
代码语言:txt
复制
        AbstractApplicationContext container = new ClassPathXmlApplicationContext("User.xml");
代码语言:txt
复制
        UserBean User1 = (UserBean)container.getBean("User_singleton");
代码语言:txt
复制
        System.out.println(User1);
代码语言:txt
复制
        UserBean User2 = (UserBean)container.getBean("User_prototype");
代码语言:txt
复制
        System.out.println(User2);
代码语言:txt
复制
        container.close();
代码语言:txt
复制
    }
代码语言:txt
复制
}

结果

UserBean()构造函数undefined this is init of UserBeanundefined com.wyl.UserBean@573f2bb1undefined LifeBean()构造函数undefined this is init of UserBeanundefined com.wyl.UserBean@5ae9a829undefined ……undefined this is destory of lifeBean com.wyl.UserBean@573f2bb1

2.4.DI(依赖注入)

依赖注入Dependency

Injection,在解耦的过程中,我们将对象的创建交给Spring容器管理,当我们需要用其他类的对象,由Spring提供,我们只需在配置文件里声明即可。A类使用B类,就产生依赖关系,Spring给我们解决依赖关系就是依赖注入(DI)

2.4.1.构造器注入

代码语言:txt
复制
private String name;
代码语言:txt
复制
private Integer age;
代码语言:txt
复制
private Date birthday;
代码语言:txt
复制
// 构造函数
代码语言:txt
复制
public UserServiceImpl(String name, Integer age, Date birthday) {
代码语言:txt
复制
this.name = name;
代码语言:txt
复制
this.age = age;
代码语言:txt
复制
this.birthday = birthday;
代码语言:txt
复制
}
代码语言:txt
复制
<!-- name:按字段名称辅助;index:字段索引,给第几个字段赋值;type:指定注入值的类型,该类型也是构造函数中某个或某些字段的类型; -->
代码语言:txt
复制
<!-- value:要注入的值,基本类型和String;ref:注入其他类型数据,指向外部bean对象;这个外部bean需要存在于Spring容器 -->
代码语言:txt
复制
<bean id="userService" class="org.service.impl.UserServiceImpl">
代码语言:txt
复制
    <constructor-arg name="name" value="张三"/>
代码语言:txt
复制
    <constructor-arg name="age" value="12"/>
代码语言:txt
复制
    <constructor-arg name="birthday" ref="date"/>
代码语言:txt
复制
</bean>
代码语言:txt
复制
<!-- 创建日期对象 -->
代码语言:txt
复制
<bean id="date" class="java.util.Date"/>

2.4.2.Set方式注入

代码语言:txt
复制
private String name;
代码语言:txt
复制
private Integer age;
代码语言:txt
复制
private Date birthday;
代码语言:txt
复制
public void setName(String name) {
代码语言:txt
复制
    this.name = name;
代码语言:txt
复制
}
代码语言:txt
复制
public void setAge(Integer age) {
代码语言:txt
复制
    this.age = age;
代码语言:txt
复制
}
代码语言:txt
复制
public void setBirthday(Date birthday) {
代码语言:txt
复制
    this.birthday = birthday;
代码语言:txt
复制
}
代码语言:txt
复制
<bean id="userService2" class="org.service.impl.UserServiceImpl2">
代码语言:txt
复制
    <property name="name" value="李四"/>
代码语言:txt
复制
    <property name="age" value="12"/>
代码语言:txt
复制
    <property name="birthday" ref="date"/>
代码语言:txt
复制
</bean>
代码语言:txt
复制
<!-- 创建日期对象 -->
代码语言:txt
复制
<bean id="date" class="java.util.Date"/>

2.4.3.对象类型注入

代码语言:txt
复制
<!-- 注入对象类型属性 -->
代码语言:txt
复制
<!-- 1 配置service和dao对象 -->
代码语言:txt
复制
<bean id="userDao" class="cn.ioc.UserDao"></bean>
代码语言:txt
复制
<bean id="userService" class="cn.ioc.UserService">
代码语言:txt
复制
    <!-- 注入dao对象-->
代码语言:txt
复制
    <property name="userDao" ref="userDao"></property>
代码语言:txt
复制
</bean>

2.4.4.复杂类型注入

代码语言:txt
复制
<!-- 注入复杂类型属性值 -->
代码语言:txt
复制
  <bean id="person" class="cn.property.Person">
代码语言:txt
复制
    <!-- 数组 -->
代码语言:txt
复制
    <property name="arrs">
代码语言:txt
复制
       <list>
代码语言:txt
复制
         <value>小王</value>
代码语言:txt
复制
         <value>小马</value>
代码语言:txt
复制
         <value>小宋</value>
代码语言:txt
复制
       </list>
代码语言:txt
复制
    </property>
代码语言:txt
复制
    <!-- list -->
代码语言:txt
复制
    <property name="list">
代码语言:txt
复制
       <list>
代码语言:txt
复制
         <value>小奥</value>
代码语言:txt
复制
         <value>小金</value>
代码语言:txt
复制
         <value>小普</value>
代码语言:txt
复制
       </list>      
代码语言:txt
复制
    </property>
代码语言:txt
复制
    <!-- map -->
代码语言:txt
复制
    <property name="map">
代码语言:txt
复制
       <map>
代码语言:txt
复制
         <entry key="aa" value="lucy"></entry>
代码语言:txt
复制
         <entry key="bb" value="mary"></entry>
代码语言:txt
复制
         <entry key="cc" value="tom"></entry>
代码语言:txt
复制
       </map>
代码语言:txt
复制
    </property>
代码语言:txt
复制
    <!-- properties -->
代码语言:txt
复制
    <property name="properties">
代码语言:txt
复制
       <props>
代码语言:txt
复制
         <prop key="driverclass">com.mysql.jdbc.Driver</prop>
代码语言:txt
复制
         <prop key="username">root</prop>
代码语言:txt
复制
       </props>
代码语言:txt
复制
    </property>
代码语言:txt
复制
  </bean>
代码语言:txt
复制
<!--set-->
代码语言:txt
复制
<property name="set">
代码语言:txt
复制
            <set>
代码语言:txt
复制
                <value>LOL</value>
代码语言:txt
复制
                <value>COC</value>
代码语言:txt
复制
                <value>WOW</value>
代码语言:txt
复制
            </set>
代码语言:txt
复制
</property>
代码语言:txt
复制
<!--null-->
代码语言:txt
复制
<property name="marne">
代码语言:txt
复制
            <null/>
代码语言:txt
复制
</property>

2.4.5.拓展方式注入

代码语言:txt
复制
<beans xmlns="http://www.springframework.org/schema/beans"
代码语言:txt
复制
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
代码语言:txt
复制
       xmlns:p="http://www.springframework.org/schema/p"
代码语言:txt
复制
       xmlns:c="http://www.springframework.org/schema/c"
代码语言:txt
复制
       xsi:schemaLocation="http://www.springframework.org/schema/beans
代码语言:txt
复制
    https://www.springframework.org/schema/beans/spring-beans.xsd">
代码语言:txt
复制
</beans>

p命名注入 property

代码语言:txt
复制
<!-- p命名空间注入,可以直接注入属性的值:property -->
代码语言:txt
复制
<bean id="User"  class="com.wyl.pojo.User" p:name ="老秦" p:age ="18"/>

c命名空间注入 constructor

代码语言:txt
复制
<!-- c命名空间注入,通过构造器注入:construct-args -->
代码语言:txt
复制
<bean id="User2" class="com.wyl.pojo.User" c:age="18" c:name="老李"/>

注意点:p命名和c命名不能直接使用,需要导入xml约束

2.5.自动装配

自动装配是Spring满足bean依赖的一种方式!Spring会在上下文中自动寻找,并自动给bean装配属性。

在Spring中有三种装配的方式

  1. 在xml中显示的配置
  2. 在java中显示配置
  3. 隐式的自动装配bean

名称

说明

no

默认值,表示不使用自动装配,Bean 依赖必须通过 ref 元素定义。

byName

根据 Property 的 name 自动装配,如果一个 Bean 的 name 和另一个 Bean 中的 Property 的 name

相同,则自动装配这个 Bean 到 Property 中。

byType | 根据 Property 的数据类型(Type)自动装配,如果一个 Bean 的数据类型兼容另一个 Bean 中 Property

的数据类型,则自动装配。

constructor | 类似于 byType,根据构造方法参数的数据类型,进行 byType 模式的自动装配。

autodetect(3.0版本不支持) | 如果 Bean 中有默认的构造方法,则用 constructor 模式,否则用 byType 模式。

2.5.1.byName

代码语言:txt
复制
<!--
代码语言:txt
复制
byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid!
代码语言:txt
复制
-->
代码语言:txt
复制
<bean id="people" class="com.wyl.pojo.People" autowire="byName">
代码语言:txt
复制
    <property name="name" value="wangyanling"/>
代码语言:txt
复制
</bean>

2.5.2.byType

代码语言:txt
复制
<bean id="cat" class="com.wyl.pojo.Cat"/>
代码语言:txt
复制
    <bean id="dog" class="com.wyl.pojo.Dog"/>
代码语言:txt
复制
    <!--
代码语言:txt
复制
    byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid!
代码语言:txt
复制
    byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean!
代码语言:txt
复制
    -->
代码语言:txt
复制
    <bean id="people" class="com.wyl.pojo.People" autowire="byType">
代码语言:txt
复制
        <property name="name" value="WANGAYNLING"/>
代码语言:txt
复制
    </bean>

2.5.3.注解

jdk1.5支持的注解,Spring2.5就支持注解了!

要使用注解须知:

  1. 导入约束 context约束
  2. 配置注解的支持: context:annotation-config/
代码语言:txt
复制
    <?xml version="1.0" encoding="UTF-8"?>
代码语言:txt
复制
<beans xmlns="http://www.springframework.org/schema/beans"
代码语言:txt
复制
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
代码语言:txt
复制
    xmlns:context="http://www.springframework.org/schema/context"
代码语言:txt
复制
    xsi:schemaLocation="http://www.springframework.org/schema/beans
代码语言:txt
复制
        https://www.springframework.org/schema/beans/spring-beans.xsd
代码语言:txt
复制
        http://www.springframework.org/schema/context
代码语言:txt
复制
        https://www.springframework.org/schema/context/spring-context.xsd">
代码语言:txt
复制
    <context:annotation-config/>
代码语言:txt
复制
</beans>

@Autowired

@Autowired是按类型自动转配的,不支持id匹配。byType

需要导入 spring-aop的包!

直接在属性上使用即可!也可以在set方式上使用!

使用Autowired我们可以不用编写Set方法了,前提是这个自动装配的属性在IOC容器中存在,且符合名字byname。

代码语言:txt
复制
 @Autowired
代码语言:txt
复制
    private Cat cat;
代码语言:txt
复制
    @Autowired
代码语言:txt
复制
    private Dog dog;
代码语言:txt
复制
@Nullable     // 字段标记了这个注解,说明这个字段可以为null

或者 如果显示定义了Autowired的required 的属性为false ,说明这个对象可以为null,允许为空

autowired 注解应该是只能是别的,当注入

在IOC容器中该类型只有一个时,就通过byType进行装配,当注入容器存在多个同意类型的对象是,就是根据byName进行装配

如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解@Autowired完成的时候,我们可以使用@Qualifier(value=“XXX”)去配置@Autowired的使用,指定一个唯一的bean对象注入。

@Qualifier

@Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配

@Qualifier不能单独使用。

代码语言:txt
复制
public class People {
代码语言:txt
复制
    private String name;
代码语言:txt
复制
    @Autowired
代码语言:txt
复制
    @Qualifier("cat")
代码语言:txt
复制
    private Cat cat;
代码语言:txt
复制
    @Autowired
代码语言:txt
复制
    @Qualifier("dog")
代码语言:txt
复制
    private Dog dog;
代码语言:txt
复制
}

@Resource注解

  • @Resource如有指定的name属性,先按该属性进行byName方式查找装配;
  • 其次再进行默认的byName方式进行装配;
  • 如果以上都不成功,则按byType的方式自动装配。
  • 都不成功,则报异常。
代码语言:txt
复制
public class People {
代码语言:txt
复制
    private String name;
代码语言:txt
复制
    @Resource(name = "cat")
代码语言:txt
复制
    private Cat cat;
代码语言:txt
复制
    @Resource(name = "dog")
代码语言:txt
复制
    private Dog dog;

小结

@Autowired与@Resource异同:

@Autowired与@Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上。

@Autowired默认按类型装配(属于spring规范),默认情况下必须要求依赖对象必须存在,如果要允许null

值,可以设置它的required属性为false,如:@Autowired(required=false)

,如果我们想使用名称装配可以结合@Qualifier注解进行使用

@Resource(属于J2EE复返),默认按照名称进行装配,名称可以通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是

需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

它们的作用相同都是用注解方式注入对象,但执行顺序不同。@Autowired先byType,@Resource先byName。

2.6.ioc注解

@注解名称(属性名称=属性值)

2.6.1. Spring使用的注解大全和解释

注解

解释

@Controller |

组合注解(组合了@Component注解),应用在MVC层(控制层),DispatcherServlet会自动扫描注解了此注解的类,然后将web请求映射到注解了@RequestMapping的方法上。

@Service | 组合注解(组合了@Component注解),应用在service层(业务逻辑层)

@Repository | 组合注解(组合了@Component注解),应用在dao层(数据访问层)

@Component |

表示一个带注释的类是一个“组件”,成为Spring管理的Bean。当使用基于注解的配置和类路径扫描时,这些类被视为自动检测的候选对象。同时@Component还是一个元注解。

@Autowired |

Spring提供的工具(由Spring的依赖注入工具(BeanPostProcessor、BeanFactoryPostProcessor)自动注入。)

@Resource | JSR-250提供的注解

@Inject | JSR-330提供的注解

@Configuration | 声明当前类是一个配置类(相当于一个Spring配置的xml文件)

@ComponentScan | 自动扫描指定包下所有使用@Service,@Component,@Controller,@Repository的类并注册

@Bean |

注解在方法上,声明当前方法的返回值为一个Bean。返回的Bean对应的类中可以定义init()方法和destroy()方法,然后在@Bean(initMethod=”init”,destroyMethod=”destroy”)定义,在构造之后执行init,在销毁之前执行destroy。

@Aspect | 声明一个切面(就是说这是一个额外功能)

@After | 后置建言(advice),在原方法前执行。

@Before | 前置建言(advice),在原方法后执行。

@Around | 环绕建言(advice),在原方法执行前执行,在原方法执行后再执行(@Around可以实现其他两种advice)

@PointCut | 声明切点,即定义拦截规则,确定有哪些方法会被切入

@Transactional | 声明事务(一般默认配置即可满足要求,当然也可以自定义)

@Cacheable | 声明数据缓存

@EnableAspectJAutoProxy | 开启Spring对AspectJ的支持

@Value | 值得注入。经常与Sping

EL表达式语言一起使用,注入普通字符,系统属性,表达式运算结果,其他Bean的属性,文件内容,网址请求内容,配置文件属性值等等

@PropertySource |

指定文件地址。提供了一种方便的、声明性的机制,用于向Spring的环境添加PropertySource。与@configuration类一起使用。

@PostConstruct | 标注在方法上,该方法在构造函数执行完成之后执行。

@PreDestroy | 标注在方法上,该方法在对象销毁之前执行。

@Profile |

表示当一个或多个指定的文件是活动的时,一个组件是有资格注册的。使用@Profile注解类或者方法,达到在不同情况下选择实例化不同的Bean。@Profile(“dev”)表示为dev时实例化。

@EnableAsync | 开启异步任务支持。注解在配置类上。

@Async | 注解在方法上标示这是一个异步方法,在类上标示这个类所有的方法都是异步方法。

@EnableScheduling | 注解在配置类上,开启对计划任务的支持。

@Scheduled | 注解在方法上,声明该方法是计划任务。支持多种类型的计划任务:cron,fixDelay,fixRate

@Conditional | 根据满足某一特定条件创建特定的Bean

@Enable* | 通过简单的@Enable 来开启一项功能的支持。所有@Enable

注解都有一个@Import注解,@Import是用来导入配置类的,这也就意味着这些自动开启的实现其实是导入了一些自动配置的Bean(1.直接导入配置类2.依据条件选择配置类3.动态注册配置类)

@RunWith |

这个是Junit的注解,springboot集成了junit。一般在测试类里使用:@RunWith(SpringJUnit4ClassRunner.class)

— SpringJUnit4ClassRunner在JUnit环境下提供Sprng TestContext Framework的功能

@ContextConfiguration |

用来加载配置ApplicationContext,其中classes属性用来加载配置类:@ContextConfiguration(classes =

{TestConfig.class(自定义的一个配置类)})

@ActiveProfiles | 用来声明活动的profile–@ActiveProfiles(“prod”(这个prod定义在配置类中))

@EnableWebMvc |

用在配置类上,开启SpringMvc的Mvc的一些默认配置:如ViewResolver,MessageConverter等。同时在自己定制SpringMvc的相关配置时需要做到两点:1.配置类继承WebMvcConfigurerAdapter类2.就是必须使用这个@EnableWebMvc注解。

@RequestMapping |

用来映射web请求(访问路径和参数),处理类和方法的。可以注解在类和方法上,注解在方法上的@RequestMapping路径会继承注解在类上的路径。同时支持Serlvet的request和response作为参数,也支持对request和response的媒体类型进行配置。其中有value(路径),produces(定义返回的媒体类型和字符集),method(指定请求方式)等属性。

@ResponseBody | 将返回值放在response体内。返回的是数据而不是页面

@RequestBody | 允许request的参数在request体中,而不是在直接链接在地址的后面。此注解放置在参数前。

@PathVariable | 放置在参数前,用来接受路径参数。

@RestController |

组合注解,组合了@Controller和@ResponseBody,当我们只开发一个和页面交互数据的控制层的时候可以使用此注解。

@ControllerAdvice | 用在类上,声明一个控制器建言,它也组合了@Component注解,会自动注册为Spring的Bean。

@ExceptionHandler |

用在方法上定义全局处理,通过他的value属性可以过滤拦截的条件:@ExceptionHandler(value=Exception.class)–表示拦截所有的Exception。

@ModelAttribute |

将键值对添加到全局,所有注解了@RequestMapping的方法可获得次键值对(就是在请求到达之前,往model里addAttribute一对name-

value而已)。

@InitBinder |

通过@InitBinder注解定制WebDataBinder(用在方法上,方法有一个WebDataBinder作为参数,用WebDataBinder在方法内定制数据绑定,例如可以忽略request传过来的参数Id等)。

@WebAppConfiguration |

一般用在测试上,注解在类上,用来声明加载的ApplicationContext是一个WebApplicationContext。他的属性指定的是Web资源的位置,默认为src/main/webapp,我们可以修改为:@WebAppConfiguration(“src/main/resources”)。

@EnableAutoConfiguration | 此注释自动载入应用程序所需的所有Bean——这依赖于Spring

Boot在类路径中的查找。该注解组合了@Import注解,@Import注解导入了EnableAutoCofigurationImportSelector类,它使用SpringFactoriesLoader.loaderFactoryNames方法来扫描具有META-

INF/spring.factories文件的jar包。而spring.factories里声明了有哪些自动配置。

@SpingBootApplication |

SpringBoot的核心注解,主要目的是开启自动配置。它也是一个组合注解,主要组合了@Configurer,@EnableAutoConfiguration(核心)和@ComponentScan。可以通过@SpringBootApplication(exclude={想要关闭的自动配置的类名.class})来关闭特定的自动配置。

@ImportResource |

虽然Spring提倡零配置,但是还是提供了对xml文件的支持,这个注解就是用来加载xml配置的。例:@ImportResource({“classpath

@ConfigurationProperties |

将properties属性与一个Bean及其属性相关联,从而实现类型安全的配置。例:@ConfigurationProperties(prefix=”authot”,locations={“classpath

@ConditionalOnBean | 条件注解。当容器里有指定Bean的条件下。

@ConditionalOnClass | 条件注解。当类路径下有指定的类的条件下。

@ConditionalOnExpression | 条件注解。基于SpEL表达式作为判断条件。

@ConditionalOnJava | 条件注解。基于JVM版本作为判断条件。

@ConditionalOnJndi | 条件注解。在JNDI存在的条件下查找指定的位置。

@ConditionalOnMissingBean | 条件注解。当容器里没有指定Bean的情况下。

@ConditionalOnMissingClass | 条件注解。当类路径下没有指定的类的情况下。

@ConditionalOnNotWebApplication | 条件注解。当前项目不是web项目的条件下。

@ConditionalOnResource | 条件注解。类路径是否有指定的值。

@ConditionalOnSingleCandidate | 条件注解。当指定Bean在容器中只有一个,后者虽然有多个但是指定首选的Bean。

@ConditionalOnWebApplication | 条件注解。当前项目是web项目的情况下。

@EnableConfigurationProperties |

注解在类上,声明开启属性注入,使用@Autowired注入。例:@EnableConfigurationProperties(HttpEncodingProperties.class)。

@AutoConfigureAfter |

在指定的自动配置类之后再配置。例:@AutoConfigureAfter(WebMvcAutoConfiguration.class)

2.6.1.1.创建对象的注解
  • @Component(标注当前类是Spring容器中的一个组件)
  • @Repository(一般用于持久层)
  • @Service(一般用于业务层)
  • @Controller(一般用于表现层)
2.6.1.2、注入数据的注解
  • @Autowired:自动按类型注入,常用在变量上;如果容器中有唯一一个类型与注解的变量类型相同则可以自动注入成功。当有多个bean匹配则按照变量名称去查找,找不到则注入失败。
  • @Qualifier("userDaoImpl"):结合@Autowired使用,注入指定名称的bean; 在类的成员变量上不能单独使用;在方法参数里使用可以单独使用;
  • @Resource:相当于@Autowired自动注入,而@Resource(name="xxx")注入指定的bean,相当于同时使用@Autowired和@Qualifier("userDaoImpl")两个注解。

上面三个注解都只能注入其他的bean类型,不能注入基本数据类型和String和复杂类型;复杂类型只能通过xml文件来注入。

  • @Value:注入基本数据类型和String类型。指定数据的值,写法:${表达式}。
2.6.1.3、改变作用范围的注解
  • @Scope:取值有singleton单例(默认)和prototype多例
2.6.1.4、和生命周期相关注解
代码语言:txt
复制
@PostConstruct
代码语言:txt
复制
public void init() {
代码语言:txt
复制
    System.out.println("初始化注解");
代码语言:txt
复制
}
代码语言:txt
复制
@PreDestroy
代码语言:txt
复制
public void destroy() {
代码语言:txt
复制
    System.out.println("销毁注解");
代码语言:txt
复制
}

这两个注解和bean标签里面的init-method、destroy-method作用相同。

2.6.1.5.新注解
  • @Configuration:作用在类上面标明当前类是一个配置类
  • @ComponentScan(basePackages = "com.wyl"):扫描包注解:相当于下面这一行配置
代码语言:txt
复制
    <!--<context:component-scan base-package="com.wyl"/>-->
  • @Bean:在配置类中写在方法上,将方法返回的对象注入到Spring容器中。该注解的方法有参数时,会去容器中找bean对象,跟@Autowired注解一样的。
  • @PropertySource("classpath:db.properties"):指定数据库配置文件的位置
  • @Import:存在多个配置文件,用该注解引入其他配置文件。
2.6.1.6.Spring测试注解
代码语言:txt
复制
@RunWith(SpringJUnit4ClassRunner.class)
代码语言:txt
复制
@ContextConfiguration(classes = ApplicationConfig.class) 纯注解
代码语言:txt
复制
// @ContextConfiguration(locations = "classpath:ApplicationContext.xml") xml配置文件
代码语言:txt
复制
public class SpringTest {
代码语言:txt
复制
    @Autowired
代码语言:txt
复制
    private AccountServiceImpl accountService;
代码语言:txt
复制
    @Test
代码语言:txt
复制
    public void findAll(){
代码语言:txt
复制
        List<Account> accountList = accountService.findAll();
代码语言:txt
复制
        for (Account account : accountList) {
代码语言:txt
复制
            System.out.println(account);
代码语言:txt
复制
        }
代码语言:txt
复制
    }
代码语言:txt
复制
}

@RunWith(SpringJUnit4ClassRunner.class):替换掉原来junit的runner执行方法,使用Spring自己的执行方法。

@ContextConfiguration(classes =

ApplicationConfig.class):如果是使用注解创建Spring的容器使用classes;

@ContextConfiguration(locations =

"classpath:ApplicationContext.xml"):使用xml配置文件的方法

2.6.2.基于xml方式创建bean

代码语言:txt
复制
public class User {
代码语言:txt
复制
    private Integer id;
代码语言:txt
复制
    private String name;
代码语言:txt
复制
}
代码语言:txt
复制
<?xml version="1.0" encoding="UTF-8"?>
代码语言:txt
复制
<beans xmlns="http://www.springframework.org/schema/beans"
代码语言:txt
复制
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
代码语言:txt
复制
       xsi:schemaLocation="http://www.springframework.org/schema/beans        
代码语言:txt
复制
       http://www.springframework.org/schema/beans/spring-beans.xsd">
代码语言:txt
复制
    <bean id="user" class="com.wyl.bean.User" >
代码语言:txt
复制
        <property name="id" value="1"></property>
代码语言:txt
复制
        <property name="name" value="wyl"></property>
代码语言:txt
复制
    </bean>
代码语言:txt
复制
</beans>
代码语言:txt
复制
@test
代码语言:txt
复制
public void UserTest{
代码语言:txt
复制
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("Bean.xml");
代码语言:txt
复制
        User userInfo=(User)context.getBean("user");
代码语言:txt
复制
        System.out.println(userInfo);
代码语言:txt
复制
}

2.6.3. 基于@Configuration 和@Bean 注解

Configuration 配置类

代码语言:txt
复制
@Configuration
代码语言:txt
复制
public class MyTestConfig {
代码语言:txt
复制
    //bean的id默认为方法名
代码语言:txt
复制
    @Bean
代码语言:txt
复制
    public User user(){
代码语言:txt
复制
        User user =new User();
代码语言:txt
复制
        user.setName("王延领");
代码语言:txt
复制
        user.setId(2);
代码语言:txt
复制
        return user;
代码语言:txt
复制
    }
代码语言:txt
复制
}
代码语言:txt
复制
@test
代码语言:txt
复制
public void UserTest{
代码语言:txt
复制
    AnnotationConfigApplicationContext context=new                          AnnotationConfigApplicationContext(MyTestConfig.class);
代码语言:txt
复制
        User userInfo=(User)context.getBean("user");
代码语言:txt
复制
        System.out.println(userInfo.toString());
代码语言:txt
复制
        }

3.Spring核心AOP

AOP(Aspect Oriented

Programming):面向切面编程,在不修改源代码的情况下增强代码的功能。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

image-20210901112213781

3.1.AOP实现原理代理模式

代理模式,创建一个代理对象实现和被对代理对象相同的接口,这样就拥有和被代理对象相同的功能,在这基础上增强原有的方法。

  • 静态代理,手动去实现一个代理类
  • 动态代理,通过反射动态的实现代理类

3.1.1 静态代理

步骤:

  1. 抽象角色 : 一般使用接口或者抽象类来实现
代码语言:txt
复制
    public interface Rent {
代码语言:txt
复制
    public void rent();
代码语言:txt
复制
}
  1. 真实角色 : 被代理的角色
代码语言:txt
复制
    public class Host implements Rent{
代码语言:txt
复制
    @Override
代码语言:txt
复制
    public void rent() {
代码语言:txt
复制
        System.out.println("房东出租房子!");
代码语言:txt
复制
    }
代码语言:txt
复制
}
  1. 代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作 .
代码语言:txt
复制
    public class Proxy {
代码语言:txt
复制
    private Host host;
代码语言:txt
复制
    public Proxy(){
代码语言:txt
复制
    }
代码语言:txt
复制
    public Proxy(Host host){
代码语言:txt
复制
        this.host=host;
代码语言:txt
复制
    }
代码语言:txt
复制
    public void rent(){
代码语言:txt
复制
        seeHouse();
代码语言:txt
复制
        host.rent();
代码语言:txt
复制
        hetong();
代码语言:txt
复制
        fare();
代码语言:txt
复制
    }
代码语言:txt
复制
    public void seeHouse(){
代码语言:txt
复制
        System.out.println("中介带你看房");
代码语言:txt
复制
    }
代码语言:txt
复制
    public void fare(){
代码语言:txt
复制
        System.out.println("收中介费!");
代码语言:txt
复制
    }
代码语言:txt
复制
    public void hetong(){
代码语言:txt
复制
        System.out.println("签租领合同");
代码语言:txt
复制
    } 
代码语言:txt
复制
}
  1. 客户 : 使用代理角色来进行一些操作 .
代码语言:txt
复制
public class Client {
代码语言:txt
复制
    public static void main(String[] args) {
代码语言:txt
复制
        Host host=new Host();
代码语言:txt
复制
        //host.rent();
代码语言:txt
复制
        Proxy proxy=new Proxy(host);
代码语言:txt
复制
        proxy.rent();
代码语言:txt
复制
    }
代码语言:txt
复制
}

好处:

  • 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
  • 公共的业务由代理来完成 . 实现了业务的分工 ,
  • 公共业务发生扩展时变得更加集中和方便 .

缺点 :

  • 类多了 , 多了代理类 , 工作量变大了 . 开发效率降低 .undefined我们想要静态代理的好处,又不想要静态代理的缺点,所以 , 就有了动态代理

3.1.2.动态代理

动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的

动态代理分为两类 :

  1. 基于接口的动态代理----JDK动态代理
代码语言:txt
复制
    //抽象角色:租房
代码语言:txt
复制
public interface Rent {
代码语言:txt
复制
    public void rent();
代码语言:txt
复制
}
代码语言:txt
复制
//真实角色: 房东,房东要出租房子
代码语言:txt
复制
public class Host implements Rent{
代码语言:txt
复制
    public void rent() {
代码语言:txt
复制
        System.out.println("房屋出租");
代码语言:txt
复制
    }
代码语言:txt
复制
}
代码语言:txt
复制
//代理:中介
代码语言:txt
复制
public class ProxyInvocationHandler implements InvocationHandler {
代码语言:txt
复制
    private Rent rent;
代码语言:txt
复制
    public void setRent(Rent rent) {
代码语言:txt
复制
        this.rent = rent;
代码语言:txt
复制
    }
代码语言:txt
复制
    //生成代理类,重点是第二个参数,获取要代理的抽象角色!之前都是一个角色,现在可以代理一类角色
代码语言:txt
复制
    public Object getProxy(){
代码语言:txt
复制
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
代码语言:txt
复制
                rent.getClass().getInterfaces(),this);
代码语言:txt
复制
    }
代码语言:txt
复制
    // proxy : 代理类 method : 代理类的调用处理程序的方法对象.
代码语言:txt
复制
    // 处理代理实例上的方法调用并返回结果
代码语言:txt
复制
    @Override
代码语言:txt
复制
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
代码语言:txt
复制
        seeHouse();
代码语言:txt
复制
        //核心:本质利用反射实现!
代码语言:txt
复制
        Object result = method.invoke(rent, args);
代码语言:txt
复制
        fare();
代码语言:txt
复制
        return result;
代码语言:txt
复制
    }
代码语言:txt
复制
    //看房
代码语言:txt
复制
    public void seeHouse(){
代码语言:txt
复制
        System.out.println("带房客看房");
代码语言:txt
复制
    }
代码语言:txt
复制
    //收中介费
代码语言:txt
复制
    public void fare(){
代码语言:txt
复制
        System.out.println("收中介费");
代码语言:txt
复制
    }
代码语言:txt
复制
}
代码语言:txt
复制
//租客
代码语言:txt
复制
public class Client {
代码语言:txt
复制
    public static void main(String[] args) {
代码语言:txt
复制
        //真实角色
代码语言:txt
复制
        Host host = new Host();
代码语言:txt
复制
        //代理实例的调用处理程序
代码语言:txt
复制
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
代码语言:txt
复制
        pih.setRent(host); //将真实角色放置进去!
代码语言:txt
复制
        Rent proxy = (Rent)pih.getProxy(); //动态生成对应的代理类!
代码语言:txt
复制
        proxy.rent();
代码语言:txt
复制
    }
代码语言:txt
复制
}
  1. 基于类的动态代理–cglib
代码语言:txt
复制
// 被代理的对象
代码语言:txt
复制
Account account = new Account();
代码语言:txt
复制
Account o = (Account) Enhancer.create(account.getClass(), new MethodInterceptor() {
代码语言:txt
复制
    /**
代码语言:txt
复制
    * 被代理对象的方法执行前会执行
    * @param obj 被代理的对象
    * @param method 方法
    * @param objects 参数
    * @param methodProxy 当前执行方法的代理的对象
    * @return 和被代理对象的方法相同的返回值
    * @throws Throwable 异常
    */
    @Override
    public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("增强前...");
        Object invoke = method.invoke(account, objects);
        System.out.println("增强后...");
        return invoke;
    }
});
o.findAll();

3.2.AOP术语

  • Joinpoint(连接点):指的是方法,可以被动态代理增强的方法就是连接点,Spring只支持方法类型的连接点
  • Pointcut(切入点):定义要对哪些Joinpoint连接点(方法)进行拦截增强功能。 被增强的方法叫做切入点,所有的方法都可以看做是一个连接点。只有被增强了的方法才叫做切入点。
  • Advice(通知/增强):拦截到Jointpoint(连接点)之后要做的事情就是通知。通知的类型:前置通知、后置通知、最终通知、环绕通知、异常通知。
  • Introduction(引介):一种特殊的通知,在不修改代码的前提下,可以在运行期为类动态的添加一些方法或字段。
  • Target(目标对象):代理的目标对象
  • Weaving(织入):是把增强 应用到 目标对象来创建新的代理对象的过程(添加新功能代码的过程)。Spring采用的是动态代理织入,而AspectJ采用编译期和类装载织入。
  • Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类。
  • Aspect(切面):是切入点和通知(引介)的结合。

3.3.使用Spring实现Aop

代码语言:txt
复制
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
代码语言:txt
复制
<dependency>
代码语言:txt
复制
    <groupId>org.aspectj</groupId>
代码语言:txt
复制
    <artifactId>aspectjweaver</artifactId>
代码语言:txt
复制
    <version>1.9.4</version>
代码语言:txt
复制
</dependency>

3.3.1.通过 Spring API 实现

代码语言:txt
复制
//接口与业务
代码语言:txt
复制
public interface UserService {
代码语言:txt
复制
    public void add();
代码语言:txt
复制
    public void delete();
代码语言:txt
复制
    public void update();
代码语言:txt
复制
    public void search();
代码语言:txt
复制
} 
代码语言:txt
复制
public class UserServiceImpl implements UserService{
代码语言:txt
复制
    @Override
代码语言:txt
复制
    public void add() {
代码语言:txt
复制
        System.out.println("增加用户");
代码语言:txt
复制
    }
代码语言:txt
复制
    @Override
代码语言:txt
复制
    public void delete() {
代码语言:txt
复制
        System.out.println("删除用户");
代码语言:txt
复制
    }
代码语言:txt
复制
    @Override
代码语言:txt
复制
    public void update() {
代码语言:txt
复制
        System.out.println("更新用户");
代码语言:txt
复制
    }
代码语言:txt
复制
    @Override
代码语言:txt
复制
    public void search() {
代码语言:txt
复制
        System.out.println("查询用户");
代码语言:txt
复制
    }
代码语言:txt
复制
}
代码语言:txt
复制
//增强
代码语言:txt
复制
public class AfterLog implements AfterReturningAdvice {
代码语言:txt
复制
    //returnValue 返回值
代码语言:txt
复制
    //method被调用的方法
代码语言:txt
复制
    //args 被调用的方法的对象的参数
代码语言:txt
复制
    //target 被调用的目标对象
代码语言:txt
复制
    @Override
代码语言:txt
复制
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
代码语言:txt
复制
        System.out.println("执行了" + target.getClass().getName()
代码语言:txt
复制
        +"的"+method.getName()+"方法,"
代码语言:txt
复制
        +"返回值:"+returnValue);
代码语言:txt
复制
    }
代码语言:txt
复制
}
代码语言:txt
复制
<?xml version="1.0" encoding="UTF-8"?>
代码语言:txt
复制
<beans xmlns="http://www.springframework.org/schema/beans"
代码语言:txt
复制
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
代码语言:txt
复制
       xmlns:aop="http://www.springframework.org/schema/aop"
代码语言:txt
复制
       xsi:schemaLocation="http://www.springframework.org/schema/beans
代码语言:txt
复制
        http://www.springframework.org/schema/beans/spring-beans.xsd
代码语言:txt
复制
        http://www.springframework.org/schema/aop
代码语言:txt
复制
        http://www.springframework.org/schema/aop/spring-aop.xsd">
代码语言:txt
复制
    <!--注册bean-->
代码语言:txt
复制
    <bean id="userService" class="com.wyl.service.UserServiceImpl"/>
代码语言:txt
复制
    <bean id="log" class="com.kuang.log.Log"/>
代码语言:txt
复制
    <bean id="afterLog" class="com.kuang.log.AfterLog"/>
代码语言:txt
复制
    <!--aop的配置-->
代码语言:txt
复制
    <aop:config>
代码语言:txt
复制
        <!--切入点  expression:表达式匹配要执行的方法-->
代码语言:txt
复制
        <aop:pointcut id="pointcut" expression="execution(* com.wyl.service.UserServiceImpl.*(..))"/>
代码语言:txt
复制
        <!--执行环绕; advice-ref执行方法 . pointcut-ref切入点-->
代码语言:txt
复制
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
代码语言:txt
复制
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
代码语言:txt
复制
    </aop:config>
代码语言:txt
复制
</beans>
代码语言:txt
复制
public class MyTest {
代码语言:txt
复制
    @Test
代码语言:txt
复制
    public void test(){
代码语言:txt
复制
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
代码语言:txt
复制
        UserService userService = (UserService) context.getBean("userService");
代码语言:txt
复制
        userService.search();
代码语言:txt
复制
    }
代码语言:txt
复制
}

3.3.2.自定义类来实现Aop

代码语言:txt
复制
//切入类
代码语言:txt
复制
public class DiyPointcut {
代码语言:txt
复制
    public void before(){
代码语言:txt
复制
        System.out.println("---------方法执行前---------");
代码语言:txt
复制
    }
代码语言:txt
复制
    public void after(){
代码语言:txt
复制
        System.out.println("---------方法执行后---------");
代码语言:txt
复制
    }
代码语言:txt
复制
}
代码语言:txt
复制
<!--第二种方式自定义实现-->
代码语言:txt
复制
<!--注册bean-->
代码语言:txt
复制
<bean id="diy" class="com.wyl.config.DiyPointcut"/
代码语言:txt
复制
<!--aop的配置-->
代码语言:txt
复制
<aop:config>
代码语言:txt
复制
    <!--第二种方式:使用AOP的标签实现-->
代码语言:txt
复制
    <aop:aspect ref="diy">
代码语言:txt
复制
        <aop:pointcut id="diyPonitcut" expression="execution(* com.wyl.service.UserServiceImpl.*(..))"/>
代码语言:txt
复制
        <aop:before pointcut-ref="diyPonitcut" method="before"/>
代码语言:txt
复制
        <aop:after pointcut-ref="diyPonitcut" method="after"/>
代码语言:txt
复制
    </aop:aspect>
代码语言:txt
复制
</aop:config>
代码语言:txt
复制
public class MyTest {
代码语言:txt
复制
    @Test
代码语言:txt
复制
    public void test(){
代码语言:txt
复制
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
代码语言:txt
复制
        UserService userService = (UserService) context.getBean("userService");
代码语言:txt
复制
        userService.add();
代码语言:txt
复制
    }
代码语言:txt
复制
}

3.3.3.使用注解实现AOP

代码语言:txt
复制
//注解实现的增强类
代码语言:txt
复制
package com.wyl.config;
代码语言:txt
复制
import org.aspectj.lang.ProceedingJoinPoint;
代码语言:txt
复制
import org.aspectj.lang.annotation.After;
代码语言:txt
复制
import org.aspectj.lang.annotation.Around;
代码语言:txt
复制
import org.aspectj.lang.annotation.Aspect;
代码语言:txt
复制
import org.aspectj.lang.annotation.Before;
代码语言:txt
复制
@Aspect
代码语言:txt
复制
public class AnnotationPointcut {
代码语言:txt
复制
    @Before("execution(* com.wyl.service.UserServiceImpl.*(..))")
代码语言:txt
复制
    public void before(){
代码语言:txt
复制
        System.out.println("---------方法执行前---------");
代码语言:txt
复制
    }
代码语言:txt
复制
    @After("execution(* com.wyl.service.UserServiceImpl.*(..))")
代码语言:txt
复制
    public void after(){
代码语言:txt
复制
        System.out.println("---------方法执行后---------");
代码语言:txt
复制
    }
代码语言:txt
复制
    @Around("execution(* com.wyl.service.UserServiceImpl.*(..))")
代码语言:txt
复制
    public void around(ProceedingJoinPoint jp) throws Throwable {
代码语言:txt
复制
        System.out.println("环绕前");
代码语言:txt
复制
        System.out.println("签名:"+jp.getSignature());
代码语言:txt
复制
        //执行目标方法proceed
代码语言:txt
复制
        Object proceed = jp.proceed();
代码语言:txt
复制
        System.out.println("环绕后");
代码语言:txt
复制
        System.out.println(proceed);
代码语言:txt
复制
    }
代码语言:txt
复制
}

4.事务和JdbcTemplate

4.1.JdbcTemplate使用

入门案例:

代码语言:txt
复制
// Spring自带的数据源
代码语言:txt
复制
DriverManagerDataSource dataSource = new DriverManagerDataSource();
代码语言:txt
复制
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
代码语言:txt
复制
dataSource.setUrl("jdbc:mysql://localhost:3306/spring?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai");
代码语言:txt
复制
dataSource.setUsername("root");
代码语言:txt
复制
dataSource.setPassword("root");
代码语言:txt
复制
JdbcTemplate template = new JdbcTemplate(dataSource);
代码语言:txt
复制
List<Account> accountList = template.query("select * from account", new BeanPropertyRowMapper<>(Account.class));
代码语言:txt
复制
for (Account account : accountList) {
代码语言:txt
复制
    System.out.println(account);
代码语言:txt
复制
}

具体增删改查用法:

代码语言:txt
复制
@Autowired
代码语言:txt
复制
private JdbcTemplate jdbcTemplate;
代码语言:txt
复制
// 添加
代码语言:txt
复制
@Test
代码语言:txt
复制
public void insert(){
代码语言:txt
复制
    String sql = "insert into account(name, money) VALUES (?,?)";
代码语言:txt
复制
    Account account1 = new Account();
代码语言:txt
复制
    account1.setName("迪迦");
代码语言:txt
复制
    account1.setMoney(10000F);
代码语言:txt
复制
    jdbcTemplate.update(sql, account1.getName(), account1.getMoney());
代码语言:txt
复制
    find();
代码语言:txt
复制
}
代码语言:txt
复制
// 删除
代码语言:txt
复制
@Test
代码语言:txt
复制
public void delete(){
代码语言:txt
复制
    String sql = "delete from account where id = ?";
代码语言:txt
复制
    jdbcTemplate.update(sql, 6);
代码语言:txt
复制
    find();
代码语言:txt
复制
}
代码语言:txt
复制
// 更新
代码语言:txt
复制
@Test
代码语言:txt
复制
public void update(){
代码语言:txt
复制
    List<Account> accounts = jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), 1);
代码语言:txt
复制
    Account account = accounts.get(0);
代码语言:txt
复制
    account.setName("泰罗");
代码语言:txt
复制
    String sql = "update account set name = ? where id = ?";
代码语言:txt
复制
    jdbcTemplate.update(sql, account.getName(),account.getId());
代码语言:txt
复制
    find();
代码语言:txt
复制
}
代码语言:txt
复制
// 查询所有
代码语言:txt
复制
@Test
代码语言:txt
复制
public void find(){
代码语言:txt
复制
    List<Account> accountList = jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<>(Account.class));
代码语言:txt
复制
    for (Account account : accountList) {
代码语言:txt
复制
        System.out.println(account);
代码语言:txt
复制
    }
代码语言:txt
复制
}
代码语言:txt
复制
// 查询一个bean
代码语言:txt
复制
@Override
代码语言:txt
复制
public Account findByName(String name) {
代码语言:txt
复制
    String sql = "select * from account where name = ?";
代码语言:txt
复制
    return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Account.class), name);
代码语言:txt
复制
}
代码语言:txt
复制
// 查询一个Object
代码语言:txt
复制
@Test
代码语言:txt
复制
public void findOne(){
代码语言:txt
复制
    String sql = "select count(id) from account";
代码语言:txt
复制
    Integer integer = jdbcTemplate.queryForObject(sql, Integer.class);
代码语言:txt
复制
    System.out.println(integer);
代码语言:txt
复制
}

4.2.Spring配置事务

在Spring中有两种方法管理事务:声明式事务管理和编程式事务管理;

  • 声明式事务管理:

1、xml配置文件式:

代码语言:txt
复制
    1、配置事务管理器
代码语言:txt
复制
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
代码语言:txt
复制
    <property name="dataSource" ref="dataSource"/></bean>
代码语言:txt
复制
2、配置通知
代码语言:txt
复制
<!-- 配置事务的通知/增强 -->
代码语言:txt
复制
<tx:advice id="interceptor">
代码语言:txt
复制
    <!-- 配置事务的属性 -->
代码语言:txt
复制
    <!-- isolation:事务隔离级别,默认使用数据库的隔离级别
代码语言:txt
复制
         no-rollback-for:指定一个异常,除了该异常都回滚。
代码语言:txt
复制
         propagation:事务传播行为,默认是required一定有事务,增删改设置required,查询设置supports
代码语言:txt
复制
         read-only:是否只读。只有查询才能设置true。默认是false支持读写。
代码语言:txt
复制
         rollback-for:指定一个异常,出现该异常就回滚,其他异常不回滚。
代码语言:txt
复制
         timeout:事务超时时间,默认-1,永不超时。指定了以秒为单位。 -->
代码语言:txt
复制
    <tx:attributes>
代码语言:txt
复制
        <!-- 指定在哪种规则的方法上添加事务 -->
代码语言:txt
复制
        <tx:method name="transfer*"/>
代码语言:txt
复制
    </tx:attributes>
代码语言:txt
复制
</tx:advice>
代码语言:txt
复制
3、事务管理器和切入点表达式关联起来
代码语言:txt
复制
<aop:config>
代码语言:txt
复制
    <!-- service包下所有类的所有方法都添加事务 -->
代码语言:txt
复制
    <aop:pointcut id="commonPointcut" expression="execution(* com.sample.service.*.*(..))"/>
代码语言:txt
复制
    <!-- 将事务管理器和切入点表达式关联起来 -->
代码语言:txt
复制
    <aop:advisor advice-ref="interceptor" pointcut-ref="commonPointcut"/>
代码语言:txt
复制
</aop:config>

2、注解式:

代码语言:txt
复制
    1、配置事务管理器
代码语言:txt
复制
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
代码语言:txt
复制
    <property name="dataSource" ref="dataSource"/></bean>
代码语言:txt
复制
2、开启对事务注解的支持
代码语言:txt
复制
<!-- 开启对事务注解的支持 -->
代码语言:txt
复制
<tx:annotation-driven/>
代码语言:txt
复制
3、在要添加事物的类上添加注解:@Transactional

3、纯注解式

代码语言:txt
复制
    @Configuration
代码语言:txt
复制
@ComponentScan("com.sample")
代码语言:txt
复制
// 相当于<tx:annotation-driven/>
代码语言:txt
复制
@EnableTransactionManagement
代码语言:txt
复制
@PropertySource("classpath:db.properties")
代码语言:txt
复制
public class AppConfig {
代码语言:txt
复制
    @Value("${db.driver}")
代码语言:txt
复制
    private String driver;
代码语言:txt
复制
    @Value("${db.url}")
代码语言:txt
复制
    private String url;
代码语言:txt
复制
    @Value("${db.username}")
代码语言:txt
复制
    private String username;
代码语言:txt
复制
    @Value("${db.password}")
代码语言:txt
复制
    private String password;
代码语言:txt
复制
    @Bean
代码语言:txt
复制
    public DruidDataSource dataSource(){
代码语言:txt
复制
        DruidDataSource dataSource = new DruidDataSource();
代码语言:txt
复制
        dataSource.setDriverClassName(driver);
代码语言:txt
复制
        dataSource.setUrl(url);
代码语言:txt
复制
        dataSource.setUsername(username);
代码语言:txt
复制
        dataSource.setPassword(password);
代码语言:txt
复制
        return dataSource;
代码语言:txt
复制
    }
代码语言:txt
复制
    @Bean
代码语言:txt
复制
    public JdbcTemplate jdbcTemplate(){
代码语言:txt
复制
        return new JdbcTemplate(dataSource());
代码语言:txt
复制
    }
代码语言:txt
复制
    @Bean
代码语言:txt
复制
    public DataSourceTransactionManager transactionManager(){
代码语言:txt
复制
        return new DataSourceTransactionManager(dataSource());
代码语言:txt
复制
    }
代码语言:txt
复制
}
代码语言:txt
复制
==========
代码语言:txt
复制
在类上添加@Transactional注解即可

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.1.优点
  • 1.2.缺点
  • 1.3.Spring框架的组成结构图
    • 1.3.1.核心容器
      • 1.3.2.AOP 和设备支持
        • 1.3.3.数据访问与集成
          • 1.3.4.Web
            • 1.3.5.消息(Messaging)
              • 1.3.6.Test
              • 2.Spring核心ioc
                • 2.1.ioc容器
                  • 2.1.BeanFactory 容器
                  • 2.1.2. ApplicationContext 容器
                • 2.2.使用ioc容器
                  • 2.2.1.beans.xml
                  • 2.2.2.pojo.User
                  • 2.2.2.test
                • 2.3.bean
                  • 2.3.1.定义
                  • 2.3.2.创建
                  • 2.3.2.配置
                  • 2.3.3.作用域
                  • 2.3.4.生命周期
                • 2.4.DI(依赖注入)
                  • 2.4.1.构造器注入
                  • 2.4.2.Set方式注入
                  • 2.4.3.对象类型注入
                  • 2.4.4.复杂类型注入
                  • 2.4.5.拓展方式注入
                • 2.5.自动装配
                  • 2.5.1.byName
                  • 2.5.2.byType
                  • 2.5.3.注解
                • 2.6.ioc注解
                  • 2.6.1. Spring使用的注解大全和解释
                  • 2.6.2.基于xml方式创建bean
                  • 2.6.3. 基于@Configuration 和@Bean 注解
              • 3.Spring核心AOP
                • 3.1.AOP实现原理代理模式
                  • 3.1.1 静态代理
                  • 3.1.2.动态代理
                • 3.2.AOP术语
                  • 3.3.使用Spring实现Aop
                    • 3.3.1.通过 Spring API 实现
                    • 3.3.2.自定义类来实现Aop
                    • 3.3.3.使用注解实现AOP
                • 4.事务和JdbcTemplate
                  • 4.1.JdbcTemplate使用
                    • 4.2.Spring配置事务
                    相关产品与服务
                    容器服务
                    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档