张嘉锡V

导航

 

Spring简要介绍: 一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。

  • 优点:
  1. Spring是一个开源免费的框架,容器.
  2. Spring是一个轻量级的框架,非侵入式的.
  3. 控制反转IoC,面向切面Aop
  4. 对事物的支持,对框架的支持
  • 组成:
    image
  1. 核心容器(Spring Core)

  核心容器提供Spring框架的基本功能。Spring以bean的方式组织和管理Java应用中的各个组件及其关系。Spring使用BeanFactory来产生和管理Bean,它是工厂模式的实现。BeanFactory使用控制反转(IoC)模式将应用的配置和依赖性规范与实际的应用程序代码分开。

  1. 应用上下文(Spring Context)

  Spring上下文是一个配置文件,向Spring框架提供上下文信息。Spring上下文包括企业服务,如JNDI、EJB、电子邮件、国际化、校验和调度功能。

  1. Spring面向切面编程(Spring AOP)

  通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring框架中。所以,可以很容易地使 Spring框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。

  1. JDBC和DAO模块(Spring DAO)

  JDBC、DAO的抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理,和不同数据库供应商所抛出的错误信息。异常层次结构简化了错误处理,并且极大的降低了需要编写的代码数量,比如打开和关闭链接。

  1. 对象实体映射(Spring ORM)

  Spring框架插入了若干个ORM框架,从而提供了ORM对象的关系工具,其中包括了Hibernate、JDO和 IBatis SQL Map等,所有这些都遵从Spring的通用事物和DAO异常层次结构。

  1. Web模块(Spring Web)

  Web上下文模块建立在应用程序上下文模块之上,为基于web的应用程序提供了上下文。所以Spring框架支持与Struts集成,web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。

  1. MVC模块(Spring Web MVC)

  MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的。MVC容纳了大量视图技术,其中包括JSP、POI等,模型来有JavaBean来构成,存放于m当中,而视图是一个街口,负责实现模型,控制器表示逻辑代码,由c的事情。Spring框架的功能可以用在任何J2EE服务器当中,大多数功能也适用于不受管理的环境。Spring的核心要点就是支持不绑定到特定J2EE服务的可重用业务和数据的访问的对象,毫无疑问这样的对象可以在不同的J2EE环境,独立应用程序和测试环境之间重用。

  • Spring Boot: 构建
  • Spring Cloud:协调
  • Spring Cloud Data Flow: 连接

IOC

实例

  1. UserDao接口
// interface: UserDao
package dao;
public interface UserDao {
    void getUser();
}
  1. UserDaoImpl实现类
// 针对不同的需求,设计实现了多个该接口的实现类

// implements01: UserDaoImpl
package dao;

public class UserDaoImpl implements UserDao {
    @Override
    public void getUser() {
        System.out.println("get the data from user");
    }
}

// implements02: UserDaoMysqlImpl
package dao;

public class UserDaoMysqlImpl implements UserDao {
    @Override
    public void getUser() {
        System.out.println("Mysql: get the data from user");
    }
}

// implements03:UserDaoOracleImpl
package dao;

public class UserDaoOracleImpl implements UserDao {
    @Override
    public void getUser() {
        System.out.println("Oracle: get the data from user");
    }
}
  1. UserService业务接口
package service;

import dao.UserDao;

public interface UserService {
    // 满足不同需求
    void setUserDao(UserDao userDao);
    void getUser();
}
  1. UserServiceImpl业务实现类
package service;

import dao.UserDao;

public class UserServiceImpl implements UserService{

    private UserDao userDao;
    // 在业务层,根据不同需求,返回实现满足不同需求的服务
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void getUser() {
        userDao.getUser();
    }
}
  1. Test
import dao.UserDaoImpl;
import dao.UserDaoMysqlImpl;
import dao.UserDaoOracleImpl;
import service.UserService;
import service.UserServiceImpl;

public class MyTest {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        userService.setUserDao(new UserDaoImpl());
        userService.getUser();

        userService.setUserDao(new UserDaoMysqlImpl());
        userService.getUser();

        userService.setUserDao(new UserDaoOracleImpl());
        userService.getUser();
    }
}

  • 将主动权交给用户

HelloSpring

<?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">

    <!--bean就是java对象 , 由Spring创建和管理-->
    <!-- id: 变量名 -->
    <bean id="hello" class="pojo.Hello">
        <property name="str" value="Spring"/>
    </bean>

</beans>
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.Hello;

public class Mytest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        // 获取到由spring创建的对象
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello.toString());
    }
}

实例改进

  • 配置文件
<?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">

    <!--bean就是java对象 , 由Spring创建和管理-->
    <bean id="mysqlImpl" class="dao.UserDaoMysqlImpl"/>
    <bean id="oracleImpl" class="dao.UserDaoOracleImpl"/>
    <bean id="userServiceImpl" class="service.UserServiceImpl">
        <!-- ref: 应用spring容器中创建好的对象 -->
        <!-- value:基本数据类型 -->
        <property name="userDao" ref="oracleImpl"/>
    </bean>

</beans>
  • Test
import dao.UserDaoImpl;
import dao.UserDaoMysqlImpl;
import dao.UserDaoOracleImpl;
import javafx.application.Application;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.UserService;
import service.UserServiceImpl;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        UserServiceImpl userService = (UserServiceImpl) context.getBean("userServiceImpl");
        userService.getUser();
    }
}

IOC创建对象的方式

package pojo;

public class User {
    private String name;

    public User() {
        System.out.println("调用了无参构造方法");
    }

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("调用了set方法");
        this.name = name;
    }

    public void show() {
        System.out.println("name = " + name);
    }
}

  • 下标
<bean id="user" class="pojo.User">
    <constructor-arg index="0" value="zcs"/>
</bean>
  • 通过类型创建
<bean id="user" class="pojo.User">
    <constructor-arg type="java.lang.String" value="zcs"/>
</bean>
  • 通过参数名
<bean id="user" class="pojo.User">
    <constructor-arg name="name" value="zcs"/>
</bean>
  • 结论:在配置文件加载的时候。其中管理的对象都已经初始化了!

配置

  • Alias: 别名
<alias name="user" alias="userNew>
  • Bean

id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
如果配置id,又配置了name,那么name是别名
name可以设置多个别名,可以用逗号,分号,空格隔开
如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;

  • import
<import resource="{path}/beans.xml"/>

依赖注入

构造器注入

依赖:bean对象的创建依赖
注入:bean中所有属性,由容器注入

  • array
<property name="books">
        <array>
            <value>西游记</value>
            <value>红楼梦</value>
            <value>水浒传</value>
        </array>
    </property>
  • list
<property name="hobbys">
    <list>
        <value>听歌</value>
        <value>看电影</value>
        <value>爬山</value>
    </list>
</property>

  • map
<property name="card">
    <map>
        <entry key="中国邮政" value="456456456465456"/>
        <entry key="建设" value="1456682255511"/>
    </map>
</property>
  • set
<property name="games">
    <set>
        <value>LOL</value>
        <value>BOB</value>
        <value>COC</value>
    </set>
</property>
  • 空指针
<property name="wife"><null/></property>
  • properties
<property name="info">
    <props>
        <prop key="学号">20190604</prop>
        <prop key="性别">男</prop>
        <prop key="姓名">小明</prop>
    </props>
</property>
  • P命名空间注入:需要在头文件中加入约束文件
 导入约束 : xmlns:p="http://www.springframework.org/schema/p"
 <!-- 直接通过注入属性的值 -->
<bean id="user" class="pojo.User" p:name="zcs" p:age="21"/>
  • C命名空间注入:
导入约束 : xmlns:c="http://www.springframework.org/schema/c"
 <!--C(构造: Constructor)命名空间 , 属性依然要设置set方法-->
<bean id="user" class="pojo.User" c:name="zcs" p:age="21"/>

Bean作用域

  • Bean:在Spring中,那些组成应用程序的主体及由Spring IoC容器所管理的对象,bean就是由IoC容器初始化、装配及管理的对象

  • singleton:默认以单例模式存在
    当一个bean的作用域为Singleton,那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。注意,Singleton作用域是Spring中的缺省作用域。要在XML中将bean定义成singleton,可以这样配置:

<bean id="serviceImpl class="service.serviceImpl" scope="singleton">
  • prototype:原型模式,每次从容器中get的时候,都会产生一个新对象
    <bean id="serviceImpl class="service.serviceImpl" scope="prototype">
  • request、session、application只能在web开发中使用

自动装配

  • spring满足bean依赖的一种方式

  • spring会在上下文中自动寻找,并自动给bean装配属性

  • 三种装配方式:

  1. xml
  2. java
  3. 隐式的自动装配
    byName:自动在容器上下文查找,和自己对象set方法后面的值对应的beanid,需保证所有bean的id唯一,并且和这个bean需要自动注入的属性的set方法一致
    byType:和自己对象属性类型相同的beanid,需保证所有bean的class唯一,并且和这个bean需要自动注入的属性的类型一致
  • 使用注解实现自动装配
<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>
</beans>

@Autowired:

  • 直接在属性上使用即可,也可以在set方式中使用
  • 使用Autowired 可以不用编写Set方法,前提是你这个自动装配的属性在IOC容器中存在,且符合名字byName

@Nullable: 此字段可以为空

public @interface Autowired {
    boolean required() default true;
}
@Autowired(required = false)

说明这个对象可以为空,否则不允许为空

@Qualifier:指定一个唯一的bean对象注入

@Qualifier(value="xxx")

@Resource:如有指定的name属性,先按该属性进行byName方式查找装配;
其次再进行默认的byName方式进行装配;
如果以上都不成功,则按byType的方式自动装配。

使用注解开发

  1. 自动装配
  2. 属性注入
@Value("zcs")
public void setName(String name) {
    this.name = name;
}
  1. 衍生注解:功能一样,将某个类注册到Spring容器中装配

@Component 有几个衍生注解,web开发中,采用MVC三层架构

  • dao @Repsitory
  • service @Service
  • controller @Controller
  1. 作用域:@Scope

JavaConfig实现配置

package pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class User {
    private String name;

    public String getName() {
        return name;
    }

    @Value("zcs")
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}
  • Config
package config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import pojo.User;

@ComponentScan("pojo")
@Configuration
public class ZcsConfig {
    
    // 注册一个Bean,相当于一个Bean标签
    // 方法名相当于id
    @Bean
    public User getUser() {
        return new User();
    }
}
  • Test
import config.ZcsConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import pojo.User;

public class MyTest {
    public static void main(String[] args) {
        // 完全使用配置内方式,通过AnnotationConfigApplicationContext获取配置类的class对象加载
        ApplicationContext context = new AnnotationConfigApplicationContext(ZcsConfig.class);
        User user = (User) context.getBean("getUser");
        System.out.println(user.getName());
    }
}

代理模式

分类:静态代理、动态代理

  • 静态代理

Proxy-01

// 要实现的Service
public interface Rent {
   public void rent();
}
public class Host implements Rent{
   public void rent() {
       System.out.println("apply Service");
  }
}

// Proxy
public class Proxy implements Rent {

    private Host host;
    public Proxy() { }
    public Proxy(Host host) {
        this.host = host;
    }

    public void additionService() {
        continue;
    }
}

Proxy-02

  • 动态代理

动态代理的代理类是动态生成的

  1. 基于接口的动态代理
    JDK动态代理

  2. 基于类的动态代理
    cglib、javasist\

JDK的动态代理:InvocationHandler、 Proxy

InvocationHandler:是一个有代理实例的调用处理程序实现的接口,每一个代理实例都有一个关联的调用处理程序\

Proxy:提供了创建动态代理类和实例的静态方法\

public Object getProxy() {
   return Proxy.newProxyInstance(this.getClass().getClassLoader(), service.getClass().getInterfaces(), this);
}
public class Host implements Service {
   public void service() {
       System.out.println("apply service");
  }
}
// 动态代理类
public class ProxyInvocationHandler implements InvocationHandler {
    private Service service;

    public void setService(Service service) {
        this.service = service;
    }

    //生成代理类,重点是第二个参数,获取要代理的抽象角色
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), service.getClass().getInterfaces(), this);
    }

    // proxy : 代理类 method : 代理类的调用处理程序的方法对象.
    // 处理代理实例上的方法调用并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        additionService();
        //核心:本质利用反射实现!
        Object result = method.invoke(service, args);
        return result;
    }

    //看房
    public void additionService(){
        System.out.println("addition Service");
    }
}
public class Client {

    public static void main(String[] args) {
        //真实角色
        Host host = new Host();
        //代理实例的调用处理程序
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setService(service); //将真实角色放置进去!
        Service proxy = (Service)pih.getProxy(); //动态生成对应的代理类!
        proxy.service();
    }
}

通用代理实现类

public class ProxyInvocationHandler implements InvocationHandler {
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    //生成代理类
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);
    }

    // proxy : 代理类
    // method : 代理类的调用处理程序的方法对象.
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());
        Object result = method.invoke(target, args);
        return result;
    }

    public void log(String methodName) {
        System.out.println("执行了"+methodName+"方法");
    }
}

Test

public class Test {
    public static void main(String[] args) {
        //真实对象
        UserServiceImpl userService = new UserServiceImpl();
        //代理对象的调用处理程序
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setTarget(userService); //设置要代理的对象
        UserService proxy = (UserService)pih.getProxy(); //动态生成代理类!
        proxy.delete();
    }
}

动态代理好处:

  1. 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .

  2. 公共的业务由代理来完成 . 实现了业务的分工 ,

  3. 公共业务发生扩展时变得更加集中和方便 .

  4. 一个动态代理 , 一般代理某一类业务

  5. 一个动态代理可以代理多个类,代理的是接口!

AOP

方式一:通过Spring API 实现

  • 设置业务接口
public interface UserService {
   public void service();
}
  • 设计业务实现类
public class UserServiceImpl implements UserService {
    System.out.println("service for user");
}
  • 两个增强类:前置和后置
public class Log implements MethodBeforeAdvice {

    //method : 要执行的目标对象的方法
    //objects : 被调用的方法的参数
    //Object : 目标对象
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println( o.getClass().getName() + "的" + method.getName() + "方法被执行了");
    }
}

public class AfterLog implements AfterReturningAdvice {
    //returnValue 返回值
    //method被调用的方法
    //args 被调用的方法的对象的参数
    //target 被调用的目标对象
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了" + target.getClass().getName()
        +"的"+method.getName()+"方法,"
        +"返回值:"+returnValue);
    }
}
  • 配置文件
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--注册bean-->
    <bean id="userService" class="service.UserServiceImpl"/>
    <bean id="log" class="log.Log"/>
    <bean id="afterLog" class="log.AfterLog"/>

    <!--aop的配置-->
    <aop:config>
        <!--切入点 expression:表达式匹配要执行的方法-->
        <aop:pointcut id="pointcut" expression="execution(* service.UserServiceImpl.*(..))"/>
        <!--执行环绕; advice-ref执行方法 . pointcut-ref切入点-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>

</beans>
  • Test
public class MyTest {
    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        UserService userService = (UserService) context.getBean("userService");
        userService.service();
    }
}
  • 输出结果
service.UserServiceImpl的service方法被执行了
service for user
执行了service.UserServiceImpl的service方法,返回值:null

Spring的Aop就是将公共的业务 (日志 , 安全等) 和领域业务结合起来 , 当执行领域业务时 , 将会把公共业务加进来 . 实现公共业务的重复利用 . 领域业务更纯粹 , 程序猿专注领域业务 , 其本质还是动态代理 .

方式二:自定义类实现AOP

  • 定义切入类
public class DiyPointcut {

    public void before(){
        System.out.println("---------方法执行前---------");
    }
    public void after(){
        System.out.println("---------方法执行后---------");
    }
   
}
  • 配置文件
<!--第二种方式自定义实现-->
<!--注册bean-->
<bean id="diy" class="com.kuang.config.DiyPointcut"/>

<!--aop的配置-->
<aop:config>
    <!--第二种方式:使用AOP的标签实现-->
    <aop:aspect ref="diy">
        <aop:pointcut id="diyPonitcut" expression="execution(* service.UserServiceImpl.*(..))"/>
        <aop:before pointcut-ref="diyPonitcut" method="before"/>
        <aop:after pointcut-ref="diyPonitcut" method="after"/>
    </aop:aspect>
</aop:config>
  • Test
public class MyTest {
    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        UserService userService = (UserService) context.getBean("userService");
        userService.add();
    }
}

方式三:使用注解实现

  • 编写注解实现的增强类
package com.kuang.config;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class AnnotationPointcut {
    @Before("execution(* service.UserServiceImpl.*(..))")
    public void before() {
        System.out.println("---------方法执行前---------");
    }

    @After("execution(* service.UserServiceImpl.*(..))")
    public void after() {
        System.out.println("---------方法执行后---------");
    }

    @Around("execution(* service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("环绕前");
        System.out.println("签名:"+jp.getSignature());
        //执行目标方法proceed
        Object proceed = jp.proceed();
        System.out.println("环绕后");
        System.out.println(proceed);
    }
}
  • 配置文件
<!--第三种方式:注解实现-->
<bean id="annotationPointcut" class="com.kuang.config.AnnotationPointcut"/>
<aop:aspectj-autoproxy/>

通过aop命名空间的<aop:aspectj-autoproxy />声明自动为spring容器中那些配置@aspectJ切面的bean创建代理,织入切面。当然,spring 在内部依旧采用AnnotationAwareAspectJAutoProxyCreator进行自动代理的创建工作,但具体实现的细节已经被<aop:aspectj-autoproxy />隐藏起来了

<aop:aspectj-autoproxy />有一个proxy-target-class属性,默认为false,表示使用jdk动态代理织入增强,当配为<aop:aspectj-autoproxy poxy-target-class="true"/>时,表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则spring将自动使用CGLib动态代理。

Spring整合Mybatis

  • spring整合数据源、mybatis
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 数据源配置 -->
    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&amp;useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=true"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

    <!-- 整合mybatis sqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="datasource"/>
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:Mapper/*.xml"/>
    </bean>

    <!-- 通过构造器自动创建sqlSessionFactory对象 -->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg ref="sqlSessionFactory"/>
    </bean>
</beans>
  • applicationContext

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


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

    <bean id="userMapper" class="Mapper.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>

</beans>
  • SQLSessionTemplate、实现类
package Mapper;

import org.mybatis.spring.SqlSessionTemplate;
import pojo.User;

import java.util.List;

public class UserMapperImpl implements UserMapper{
    private SqlSessionTemplate sqlSession;

    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }

    public List<User> selectUser() {
        return sqlSession.getMapper(UserMapper.class).selectUser();
    }
}

spring中的事务管理:声明式事务、编程式事务

编程式事务管理:

  • 将事务管理代码嵌入到业务方法中来控制事务的提交和回滚
  • 缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码

声明式事务管理:

  • 将事务管理代码从业务方法中分离出来,以声明的方式实现事务管理

  • 将事务管理作为横切关注点通过AOP方法模块化

  • 注册事务

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <property name="dataSource" ref="dataSource" />
</bean>
  • 配置事务的通知
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <!--配置哪些方法使用什么样的事务,配置事务的传播特性-->
        <tx:method name="add" propagation="REQUIRED"/>
        <tx:method name="delete" propagation="REQUIRED"/>
        <tx:method name="update" propagation="REQUIRED"/>
        <tx:method name="search*" propagation="REQUIRED"/>
        <tx:method name="get" read-only="true"/>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>
  • 配置AOP
<!--配置aop织入事务-->
<aop:config>
    <aop:pointcut id="txPointcut" expression="execution(* dao.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
posted on 2020-07-21 17:56  张嘉锡V  阅读(180)  评论(0编辑  收藏  举报