spring框架

时间:2021-04-13 10:13:09   收藏:0   阅读:40

spring框架

spring的概述

spring是什么?

spring的两大核心

IOC

? IOC是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

AOP

? 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

spring的发展历程和优势

技术分享图片

spring的体系结构

技术分享图片

程序的耦合以及解耦

之前案例中的问题

工厂模式解耦

IOC的概念和soring中的IOC

IOC的概念

技术分享图片

技术分享图片

spring中的IOC

获取spring的IOC容器,并根据id获取对象

//1.获取核心容器对象
ApplicationContext ac =new ClassPathXmlApplicationContext("bean.xml");
//2.根据id获取bean对象
IAccountService as = (IAccountService) ac.getBean("accountService");
IAccountDao adao=ac.getBean("accountDao",IAccountDao.class);

ApplicationContext的三个常用实现类

核心容器的两个接口引发出的问题

spring对bean的管理细节

     #### 创建bean的三种方式

spring中基于XML的IOC环境搭建

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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

java代码

	//1.获取核心容器对象
     ApplicationContext ac =new ClassPathXmlApplicationContext("bean.xml");
    //2.根据id获取bean对象
     IAccountService as = (IAccountService) ac.getBean("accountService");

依赖注入(Dependency Injection)

依赖注入(Dependency Injection)

IOC的作用

降低程序间的耦合(依赖关系)

依赖关系的管理

依赖注入

能注入的数据有三类

<bean id="accountService" class="service.impl.AccountServiceImpl">
    <constructor-arg name="name" value="刘某人"></constructor-arg>
    <constructor-arg name="age" value="18"></constructor-arg>
    <constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>


<!--配置一个日期对象-->
<bean id="now" class="java.util.Date">

</bean>
<bean id="accountService2" class="service.impl.AccountServiceImpl2">
    <property name="age" value="18"></property>
    <property name="name" value="矻矻"></property>
    <property name="birthday" ref="now"></property>
</bean>
<bean id="accountService3" class="service.impl.AccountServiceImpl3">
    <property name="myStrs">
        <array>
            <value>aaa</value>
            <value>bb</value>
            <value>c</value>
        </array>
    </property>
    <property name="myList">
        <list>
            <value>aaa</value>
            <value>bb</value>
            <value>c</value>
        </list>
    </property>
    <property name="myMap">
        <props>
            <prop key="testc">ccc</prop>
        </props>
    </property>
    <property name="mySet">
        <set>
            <value>aaa</value>
            <value>bb</value>
            <value>c</value>
        </set>
    </property>
    <property name="myProps">
        <map>
            <entry key="testa" value="aaa"></entry>
            <entry key="testb">
                <value>bbb</value>
            </entry>
        </map>
    </property>
</bean>

IOC注解

spring中的新注解:

在junit中,在变量上写Autowired注解为什么没用

所有由以上三点可知

? 当测试方法执行时,没有IOC容器,就算写了Autowired注解,也无法实现注入

spring整合junit的配置

AOP概念

动态代理

基于接口的动态代理:

基于子类的动态代理:

什么事AOP

? 简单来说它就是把我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的基础上,对我们的已有方法进行增强

AOP的作用和优势

AOP的实现方式

使用动态代理技术

spring中的AOP

aop相关术语

所有的切入点都是连接点,但不是所有的连接点都是切入点

学习spring中的AOP要明确的事

Spring中基于xml的AOP配置步骤

? 1.把通知的bean也交给spring来管理
? 2.使用AOP:config标签表示开始AOP的配置
? 3.使用AOP:aspect标签表明开始配置切面
? id属性:给切面提供一个唯一标志
? ref属性:是指定通知类bean的id
? 4.在aop:aspect标签的内部使用对应的标签来配置通知的类型
? 我们现在示例是让printLogger方法在切入点方法执行之前执行:所有是前置通知
? aop:before:表示配置前置通知
? method属性:用于指定Logger类中那个方法是前置通知
? pointcut属性:用于执行切入点表达式,该表达式的含义指的是对业务层中那些方法增强
? 切入点表达式的写法:
? 关键字:execution(表达式)
? 表达式:访问修饰符 返回值 包名.包名.包名....类名.方法名(参数列表)
? 标准的表达式写法:public void com.lai.service.impl.AccountServiceImpl.saveAccount()
? 访问修饰符可以省略:void com.lai.service.impl.AccountServiceImpl.saveAccount()
? 返回值可以使用通配符,表示任意返回值
? * com.lai.service.impl.AccountServiceImpl.saveAccount()
? 包名可以使用通配符,表示任意包。但是有几级包,就需要写几个*
? * ....AccountServiceImpl.saveAccount()
? 包名可以使用..表示当前包及其子包
? * ..AccountServiceImpl.saveAccount()
? 类型和方法名都可以使用
号实现通配
? * ...()
? 参数列表:
? 可以直接写数据类型:
? 基本类型直接写名称
? 引用类型写包名.类名的方式 java.lang.String
? * ...
(int)
? 可以使用通配符,表示任意类型,但是必须有参数
? * ...()
? 可以使用..表示有无 参数均可,有参数可以是任意类型
? * ...(..)
? 全通配写法:
...(..)
? 实际开发中切入表达式的通常写法
? 切到业务层实现类下的所有方法
? * com.lai.service.impl.
.*(..)

通知

<!-- 配置前置通知 -->
<aop:before method="beforePrintLog" pointcut-ref="pt1"></aop:before>
<!-- 配置后置通知 -->
<aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1" ></aop:after-returning>
<!-- 配置异常通知 -->
<aop:after-throwing method="afterThorwingPrintLog" pointcut-ref="pt1"></aop:after-throwing>
<!-- 配置最终通知 -->
<aop:after method="afterPrintLog" pointcut-ref="pt1"></aop:after>

<!-- 配置切入点表达式 ,id属性用于指定表达式的唯一标识。expression属性用于指定表达式内容
    此标签写在aop:aspect标签内部只能当做切面使用
    它还可以写在aop:aspect标签外面,此时就变成了所有切面可用,但是它必须在aop:aspect标签之前
 -->
<aop:pointcut id="pt1" expression="execution(public void com.lai.service.impl.AccountServiceImpl.saveAccount())"/>

注解

package com.lai.utils;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;

/**
 * 用于记录日志的工具类,它里面提供了公共的代码
 	当我们使用前置,后置,异常,最终通知注解来实现时最终通知会比后置通知先执行,所以如果要用注解最好使用环绕通知
 */
@Component("logger")
@Aspect//表示当前类是个切面类
public class Logger {
    @Pointcut("execution(* com.lai.service.impl.*.*(..))")
    private void pt1(){}

    /**
     * 前置通知
     */
    //@Before("pt1()")
    public void beforePrintLog(){
        System.out.println("前置通知:Logger类中的beforePrintLog开始记录日志了。。。");
    }
 /**
     * 后置通知
     */
    //@AfterReturning("pt1()")
    public void afterReturningPrintLog(){
        System.out.println("后置通知:Logger类中的afterReturningPrintLog开始记录日志了。。。");
    }
 /**
     * 异常通知
     */
    //@AfterThrowing("pt1()")
    public void afterThorwingPrintLog(){
        System.out.println("异常通知:Logger类中的afterThorwingPrintLog开始记录日志了。。。");
    }
 /**
     * 最终通知
     */
    //@After("pt1()")
    public void afterPrintLog(){
        System.out.println("最终通知:Logger类中的afterPrintLog开始记录日志了。。。");
    }

    /**
     * 环绕通知
     * 问题:
     *      当我们配置了环绕通知之后,切入点方法没有执行,而通知方法执行了
     * 分析:
     *      通过对比动态代理中的环绕通知代码,发现动态代理中的环绕通知有明确的切入点方法调用,而我们的代码中没有
     * 解决:
     *      spring框架为我们提供了一个接口:ProceedingJoinPoint 该接口有一个方法proceed。此方法就相当于明确调用切入点方法
     *      该接口可以作为环绕通知的方法参数,在程序执行时,spring框架会为我们提供该接口的实现类供我们使用。
     */
    @Around("pt1()")
    public Object aroundPrintLog(ProceedingJoinPoint pjd){
        Object rtValue = null;
        try {
            Object[] args = pjd.getArgs();//得到方法执行所需的参数
            System.out.println("前置");
            rtValue=pjd.proceed(args);//明确调用业务层方法(也叫切入点方法)
            System.out.println("后置");
            return rtValue;
        }catch (Throwable t){
            System.out.println("异常");
            throw new RuntimeException(t);
        }finally {
            System.out.println("最终");
        }


    }
}

事务控制

spring中基于xml的声明式事务控制配置步骤

<!--spring中基于xml的声明式事务控制配置步骤
        1.配置事务管理器
        2.配置事务的通知
            此时我们需要导入事务的约束 tx名称空间和约束,同时也需要AOP的
            使用tx:advice标签配置事务通知
                属性:
                    id;给事务通知起一个唯一标志
                    transaction-manager:给事务通知提供一个事务管理器阴影
        3.配置AOP中的通用切入点表达式
        4.建立事务通知和切入点表达式的对应关系
        5.配置事务的属性
            在事务的通知tx:advice标签的内部
    -->
    <!--配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>

    </bean>

    <!--配置事务的通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--配置事务的属性
        propagation:用于知道事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择,查询方法可以选择SUPPORTS
        isolation:用于指定事务隔离的级别。默认值是DEFAULT,表示使用数据库的默认隔离级别
        read-only:用于指定事务是否只读。只有查询方法才能设置为true。默认值为false,表示读写
        timeout:用于指定事务的超时时间,默认值是-1,表示永不超时。如果指定了数值以秒为单位
        no-rollback-for:用于指定一个异常,当产生当异常时,事务不回滚,产生其他异常时,事务回滚,没有默认值时,表示任何异常都回滚
        rollback-for:用于指定一个异常,当产生当异常时,事务回滚,产生其他异常时,事务不回滚,没有默认值,表示任何异常都回滚
        -->
        <tx:attributes>
            <tx:method name="transfer" propagation="REQUIRED" read-only="false"/>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>
        </tx:attributes>
    </tx:advice>

spring中基于注解的声明式事务控制配置步骤

<!--spring中基于注解的声明式事务控制配置步骤
     1.配置事务管理器
     2.开启spring对注解事务的支持
     3.在需要事务支持的地方使用@Transactional注解
 -->
 <!--配置事务管理器-->
 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
     <property name="dataSource" ref="dataSource"></property>

 </bean>
<!--开启spring对注解事务的支持-->
 <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

原文:https://www.cnblogs.com/chicaodeqingniu/p/14651557.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!