Spring

了解spring

  • spring是一个容器,容器中存放的是java对象。
    需要做的是把对象放入到容器中,让容器完成对象的创建,对象之间关系的管理(属性赋值)。
    我们在程序中从容器中获取要使用的对象

  • 什么样的对象放入容器中

    • dao类,service类,controller类,工具类

    spring中的对象默认都是单例的,在容器中叫这个名称的对象只有一个

  • 不放入到spring容器中的对象

    • 实体类对象,实体类数据来自数据库的
    • servlet,listener,filter等

使用步骤

  1. 创建maven项目

  2. 加入maven依赖

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>
    
  3. 创建类

  4. 创建spring需要使用的配置文件:applicationContext.xml

	<bean id="someService" class="cn.zbdx.service.SomeServiceImpl" />
  1. 测试spring创建的类:MyTest.java
		// 1.指定spring容器创建的对象
        String config = "beans.xml";

        // 2.创建表示spring容器的对象,ApplicationContext
        // ApplicationContext就是表示spring容器,通过容器获取对象了
        // ClassPathXmlApplicationContext:表示从类路径中加载spring的配置文件
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);

        // 从容器中获取某个对象,要调用对象的方法
        // getBean("配置文件中的bean的id值")
        SomeService someService = (SomeService) ac.getBean("someService");

        // 使用spring创建好的对象
        someService.dosome();

spring是把创建好的对象放入到map中,spring框架有一个map存放对象的。

核心技术

ioc(控制反转)

控制:创建对象,对象的属性赋值,对象之间的关系管理。

反转:把原来的开发人员管理,创建对象的权限转移给代码之外的容器实现。由容器代替开发人员管理对象,创建对象,给属性赋值。

概念:把对象的创建,赋值,管理工作都交给代码之外的容器实现,对象的创建由外部资源完成。

使用目的:减少对代码的改动,也能实现不同的功能,实现解耦合。

di技术

di:依赖注入,表示创建对象,给属性赋值

spring使用的di技术,底层使用的是反射机制

di的实现有两种:

  1. 在spring的配置文件中,使用标签和属性完成,叫做基于XML的di实现
  2. 使用spring中的注解,完成属性赋值,叫做基于注解的id实现

di给属性赋值:

  1. set注入:spring调用类的set方法,在set方法可以实现属性的赋值

    1. 简单类型的set注入:
    <bean id="myStudent" class="cn.zbdx.service.bao01.Student" >
        <property name="name" value="xz"/>
        <property name="age" value="3" />
    </bean>
    
    1. 引用类型的set注入:
    <bean id="myStudent" class="cn.zbdx.service.bao01.Student" >
        <property name="name" value="xz"/>
        <property name="age" value="3" />
        <property name="school" ref="mySchool" />
    </bean>
    
    <bean id="mySchool" class="cn.zbdx.service.bao01.School" >
        <property name="name" value="北京大学" />
        <property name="address" value="海淀区" />
    </bean>
    
  2. 构造注入:spring调用类的有参数构造方法,创建对象,在构造方法中完成赋值。

    构造注入使用<constructor-arg> 标签

    applicationContext.xml

    <bean id="myStudent" class="cn.zbdx.service.bao02.Student" >
        <constructor-arg name="name" value="wyb" />
        <constructor-arg name="age" value="3" />
        <constructor-arg name="school" ref="mySchool"/>
    </bean>
    
    <bean id="myStudent1" class="cn.zbdx.service.bao02.Student" >
        <constructor-arg index="0" value="wx" />
        <constructor-arg index="1" value="1" />
        <constructor-arg index="2" ref="mySchool"/>
    </bean>
    
    <bean id="myStudent2" class="cn.zbdx.service.bao02.Student" >
        <constructor-arg value="wxx" />
        <constructor-arg value="1" />
        <constructor-arg ref="mySchool"/>
    </bean>
    

    MyTest.java

    @Test
    public void test03() {
        String config = "/bao01/applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
    
        Student student = (Student) ac.getBean("myStudent");
        System.out.println(student);
    }
    
  3. 自动注入
    由spring根据某些规则,给引用类型完成赋值,常用的有byName,byType

    1. byName(按名称注入):java类中引用类型的属性名和spring容器中(配置文件)<bean>的id名称一样,且数据类型是一致的,这样的容器中的bean,spring能够赋值给引用类型
      语法:
    <bean id="myStudent" class="cn.zbdx.service.bao04.Student" autowire="byName">
        <property name="name" value="张三"/>
        <property name="age" value="13" />
    </bean>
    
    <bean id="school" class="cn.zbdx.service.bao04.School" >
        <property name="name" value="北京大学" />
        <property name="address" value="海淀区" />
    </bean>
    
    1. byType(按类型注入):java类中引用的数据类型和spring容器中(配置文件)<bean> 的class属性是同源关系的,这样的bean能够赋值给引用类型。
      同源就是一类的意思
      1. java类中引用类型的数据类型和bean的class的值是一样的

      2. java类中引用类型的数据类型和bean的class的值是父子关系类的

      3. java类中引用类型的数据类型和bean的class的值是接口和实现类关系的

        注意:在byType中,在xml配置文件中声明bean只能有一个符合条件的,多余一个是错误的

多配置文件

多个配置文件的优势:

  1. 每个文件的大小比一个文件要小很多,效率高
  2. 避免多人竞争带来的冲突

多文件的配置方式:

  1. 按功能模块,一个模块一个配置文件
  2. 按类的功能,数据库相关的一个配置文件,做事务的功能一个配置文件,做service功能的一个配置文件等

spring-school.xml

	<bean id="school" class="cn.zbdx.service.bao05.School" >
        <property name="name" value="北京大学" />
        <property name="address" value="海淀区" />
    </bean>

spring-student.xml

	<bean id="myStudent" class="cn.zbdx.service.bao05.Student" autowire="byName">
        <property name="name" value="张三"/>
        <property name="age" value="13" />
    </bean>

total.xml

	<!--<import resource="classpath:bao05/spring-school.xml" />
    <import resource="classpath:bao05/spring-student.xml" />-->

    <import resource="classpath:bao05/spring-*.xml" />

classpath :表示类路径(class文件所在的目录),在spring的配置文件中要指定其他文件的位置,需要使用classpath,告诉spring到哪去加载读取文件。

* :通配符,表示任意字符

注解的使用步骤

  1. 加入maven依赖
  2. 在类中加入spring的注释
  3. 在spring配置文件中,加入一个组件扫描器的标签,说明注解在项目中的位置
	<!--指定多个包的三种方式 -->
    <!-- 使用多次组件扫描器,指定不同的包 -->
    <context:component-scan base-package="cn.zbdx.bao02" />
    <context:component-scan base-package="cn.zbdx.bao03" />

    <!-- 使用分隔符;或,分隔多个包名 -->
    <context:component-scan base-package="cn.zbdx.bao02;cn.zbdx.bao03" />
    
    <!-- 指定父包 -->
    <context:component-scan base-package="cn.zbdx" />

常用的七个注解

  1. @Component:创建对象

  2. @respotory:创建dao对象,用来访问数据库的

  3. @Service:创建service对象,处理业务逻辑的,可以有事务功能

  4. @Controller:创建控制器对象的,能够接受用户提交的参数,显示请求的处理结果

    以上三个注解的使用语法和@Component一样的,都是创建对象,但是这三个注解还有额外的功能。
    @respotory,@Service,@Controller是给项目的对象分层的

  5. @Value:简单类型的属性赋值

    位置:

    1. 在属性定义的上面,无需set方法,推荐使用
    2. 在set方法的上面
  6. @Autowired:spring框架提供的注解,实现引用类型的赋值

    spring中通过注解给引用类型赋值,使用的是自动注入原理,支持byName, byType。

    @Autowired默认使用的是byType自动注入

    属性:required,是一个boolean类型的,默认true
    required = true:表示引用类型赋值失败,程序报错,并终止执行
    required =false:引用类型如果赋值失败,程序正常执行,引用类型是null

    如果要使用byName方式,需要做的是:

    1. 在属性上面加入@Autowired
    2. 在属性上面加入@Qualifier(“bean的id”):表示使用指定名称的bean完成赋值
  7. @Resource:jdk中的注解

    使用的也是自动注入原理,支持byName, byType

    默认是byName:先使用byName自动注入,如果byName赋值失败,再使用byType

    @Resource只使用byName方式,需要增加一个属性name,name的值是bean的id

AOP(面向切面编程)

  1. AOP(Aspect Orient Programming):面向切面编程,底层是动态代理,可以使用jdk,cglib两种代理方式

    1. jdk动态管理:使用jdk中的Proxy,Method,InvocationHanderl创建代理对象
      要求:目标类必须实现接口
    2. cglib动态管理:第三方的工具库,创建代理对象。
      要求:目标类不能是final的,方法也不能是final的
      原理:就是继承,子类就是代理
  2. AOP:看做是动态代理的规范化,把实现动态代理的步骤进行了一个规范,定义

  3. AOP的作用:

    1. 在目标类源代码不改变的情况下,增加功能
    2. 减少代码的重复
    3. 专注业务逻辑代码
    4. 解耦合,让业务的功能和日志,事务非业务功能分离
  4. 什么时候考虑用AOP

    1. 当你要给一个系统中存在的类修改功能,但是原有类功近乎完善,你有源代码
    2. 你要给项目中的多个类,增加一个相同的功能
    3. 给业务方方法增加事务,日志输出
  5. AOP的技术实现框架:

    1. spring:spring在内部实现了aop规范,能做aop的工作
    2. aspectJ:一个开源的专门做aop的框架。spring框架中集成了aspectJ框架,通过spring就能使用aspectJ的功能
      aspectJ实现aop有两种方式:
      1. 使用xml的配置文件,配置全局事务
      2. 使用注解,我们在项目中要做aop功能,一般都使用注解,aspectJ有五个注解
  6. AOP中的术语:

    1. Aspect:切面,表示增强的功能,就是一堆代码,完成某一个功能,非业务功能
      常见的切面功能有:日志,事务,统计信息,参数检查,权限验证
    2. JoinPoint:连接点,连接业务方法和切面的位置
    3. PointCut:切入点,指多个连接点方法的集合
    4. Advice:通知,通知表示切面功能执行的时间

aspectJ

aspectJ框架的使用:

  1. 切面的执行时间,这个执行时间在规范中叫做Advice(通知,增强)

    1. @Before:前置通知,在目标方法之前执行切面的功能
    2. @AfterReturning:后置通知,在目标方法之后执行的,能够获取到目标方法的返回值
    3. @Around:环绕通知,在目标方法前和后都能增强功能,控制目标方法的访问,修改返回值
    4. @AfterThrowing:异常通知,在目标方法抛出异常后执行的通知
    5. @After:最终通知,总是会被执行的代码
    6. @Pointcut:定义和管理切入点的辅助注解
    7. 代理的使用方法
      1. 如果目标类有接口,框架使用jdk动态代理
      2. 如果目标类无接口,默认使用cglib动态代理
      3. 有接口也可以强制使用cglib动态代理
  2. 切面执行的位置,使用的是切入点表达式

    	execution(访问权限 方法返回值 方法声明(参数) 异常类型)
    

实现步骤:

  1. 新建maven项目
  2. 加入依赖:spring,aspectJ
  3. 创建目标类:接口和他的实现类,要做的是给类中的方法增加功能
  4. 创建切面类:普通类
    1. 在类的上面加入:@Aspect
    2. 在类中定义方法,方法就是切面要执行的功能代码
      在方法的上面加入aspecctJ中的通知注解,例如@Before
      有需要指定切入点表达式execution()
  5. 创建spring的配置文件:声明对象,把对象交给容器统一管理
    声明对象可以使用注解或者xml配置文件<bean>
    1. 声明目标对象
    2. 声明切面类对象
    3. 声明aspectJ框架中的自动代理生成器标签
      自动代理生成器:用来完成代理对象的自动创建功能的
  6. 创建测试类

整合Mybatis

  1. 把mybatis框架和spring集成在一起,向一个框架一样使用

  2. 使用到的技术:ioc

  3. 原理:ioc能创建对象
    可以把mybatis框架中的对象交给spring统一创建,开发人员从spring中获取对象
    开发人员就不用同时面对两个或多个框架了,就面对一个spring

  4. 使用步骤

    1. 新建maven项目
    2. 加入maven依赖
    3. 创建实体集
    4. 创建dao接口和mapper文件
    5. 创建mybatis主配置文件
    6. 创建service接口和实现类,属性是dao
    7. 创建spring的配置文件:声明mybatis的对象交给spring创建
      1. 数据源
      2. SqlSessionFactory
      3. dao对象
      4. 声明自定义的service
    8. 创建测试类,获取service对象,通过service调用dao完成数据库的访问

Spring事务

  1. 什么是事务
    事务是指一组sql语句的集合,集合中有多条sql语句
    可能是insert,update,select,delete,我们希望这些多个sql语句都能成功,或者都失败,这些sql语句的执行是一致的,作为一个整体执行。

  2. 在什么时候想到用事务
    当我的操作,涉及得到多个表,或者是多个sql语句的insert,select,需要保证这些语句都是成功才能完成我的功能,或者都失败,保证操作是符合要求的

    在java代码中写程序,控制事务,此时事务应该放在哪里呢?
    service类的业务方法上,因为业务方法会调用多个dao方法,执行多个sql语句

  3. 多种数据库的访问技术,有不同的事务处理的机制,对象,方法

  4. 怎么解决不足?
    spring提供一种处理事务的统一模型,能使用统一步骤,方法完成多种不同数据库访问技术的事务处理

  5. 处理事务,需要怎么做,做什么
    spring处理事务的模型,使用的步骤都是固定的,把事务使用的信息提供给spring就可以了

    1. 事务内部提交,,回滚事务,使用的事务管理对象,代替你完成commit, rollback
      事务管理器是一个接口和他的众多实现类

      • 接口:PlatformTransactionManager,定义了事务重要方法 commit,rollback
      • 实现类:spring把每一种数据库访问技术对应的事务处理类都创建好了

        mybatis访问数据库–spring创建好的是DataSourceTransactionManager

      怎么使用?声明数据库访问技术对应的事务管理器实现类,在spring的配置文件中使用<bean>声明

    2. 业务方法需要什么样的事务,需要说明事务的类型
      说明方法需要的事务:

      1. 事务的隔离级别:有4 个值
        1. READ_UNCOMMITTED:读未提交
        2. READ_COMMITTED:读已提交
        3. REPEATABLE_READ:可重复读
        4. SERIALIZABLE:串行化
      2. 事务的超时时间:表示一个方法最长的执行时间,如果方法执行超过了时间,事务就回滚
      3. 事务的传播行为:控制业务方法是不是有事务的,是什么样的事务的
        7个传播行为,表示你的业务方法调用时,事务在方法之间是如何使用的。
        1. PROPAGATION_REQUIRED
        2. PROPAGATION_REQUIRES_NEW
        3. PROPAGATION_SUPPORTS
    3. 事务提交事务,回滚事务的时机

      1. 当业务方法执行成功,无异常抛出,当方法执行完毕,spring在方法执行后提交事务。事务管理器commit
      2. 当业务方法抛出运行时异常或error,spring回滚事务,调用事务管理器的rollback
      3. 当业务方法抛出非运行时异常,主要是受查异常时,提交事务
        受查异常:在代码中,必须处理的异常。例如:IOException

事务处理方案

  1. 适合中小项目使用的,注解方案
    spring框架自己用aop实现给业务方法增加事务的功能,使用@Transactional注解增加事务
    使用步骤:

    1. 声明事务管理器对象,开启事务注解驱动
      <!-- 使用spring的事务处理-->
      <!-- 声明事务管理器 -->
      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
      	<property name="dataSource" ref="myDataSource" />
      </bean>
      
      <!-- 开启事务注解驱动,告诉spring使用注解管理事务,创建代理对象-->
      <tx:annotation-driven transaction-manager="transactionManager" />
      
      1. 在你的方法上面加入@Transactional
  2. 适合大型项目。使用aspectJ框架功能,在spring配置文件中声明类,方法需要的事务

    实现步骤:

    1. 加入aspectJ依赖
    2. 声明事务管理器对象
    3. 声明方法需要的事务类型
    4. 配置aop:指定哪些类要创建你代理
	<!-- 大型项目 -->
    <!-- 1. 声明事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="myDataSource" />
    </bean>
    
    <!-- 声明业务方法它的事务属性(隔离级别,传播行为,超时时间)
        id:自定义名称,表示<tx:Advice> 和 </tx:advice> 之间的配置内容的
        transaction-manager:事务管理器对象的id
        -->
    <tx:advice id="myAdvice" transaction-manager="transactionManager">
        <!-- <tx:attributes>:配置事务属性-->
        <tx:attributes>
            <!--tx:method:给具体的方法配置事务属性,method可以有多个,分别给不同的方法设置事务属性
                name:1. 完整的方法名称,不带有包和类
                      2. 方法可以使用通配符,表示任意字符
                 propagation:传播行为,枚举值
                 isolation:隔离级别
                 rollback-for:指定的异常类名,全限定类名,发生异常一定回滚-->
            <tx:method name="buy" propagation="REQUIRED" isolation="DEFAULT"
                rollback-for="java.lang.NullPointerException, cn.zbdx.execp.NotEnoughException"/>
        </tx:attributes>
    </tx:advice>
    
	<!-- 配置aop-->
    <aop:config>
         <!-- 配置切入点表达式,指定哪些包中类,要使用事务-->
        <aop:pointcut id="servicePt" expression="execution(* *..service..*.*(..))"/>
        <!-- 配置增强器:关联Advice和pointcut-->
        <aop:advisor advice-ref="myAdvice" pointcut-ref="servicePt" />
    </aop:config>

以上为个人学习笔记,参考视频来自动力节点,若有雷同,纯属巧合。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值