zoukankan      html  css  js  c++  java
  • Spring5丶

    官方

    https://docs.spring.io/spring-framework/docs/current/reference/html/core.html

    https://repo.spring.io/release/org/springframework/spring/

    七大模块

    img

    核心容器(Spring Core)

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

    应用上下文(Spring Context)

    • Spring上下文是一个配置文件,向Spring框架提供上下文信息
    • Spring上下文包括各种企业服务

    Spring面向切面编程(Spring AOP)

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

    JDBC和DAO模块(Spring DAO)

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

    对象实体映射(Spring ORM)

    • 插入ORM框架
    • 都遵从Spring的通用事务和DAO异常层次结构

    Web模块(Spring Web)

    • Web上下文模块建立在应用程序上下文模块之上,为基于web的应用程序提供了上下文
    • web模块简化了处理多部分请求以及将请求参数绑定到域对象的工作

    MVC模块(Spring Web MVC)

    • 高度可配置的
    • 容纳了大量视图技术
    • 不绑定到特定JavaEE服务的可重用业务和数据访问的对象

    IOC 容器

    • 对象由Spring来创建、管理、装配

    • 使用set方式传入需要new的对象(由主动创建对象到被动接收对象注入)

    • DI是实现IOC的方式。

    • IOC的核心是工厂模式,AOP的核心是代理模式

    Spring 上下文

    • 创建对象,对象名为id属性值,property为对象的属性进行赋值(要求属性拥有set方法)

    依赖注入

    • 构造器注入、set方式注入、其他方式

    • p命名空间、c命名空间

    Bean 的作用域

    Scope Description
    singleton (Default) Scopes a single bean definition to a single object instance for each Spring IoC container.
    prototype Scopes a single bean definition to any number of object instances.
    request Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
    session Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
    application Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.
    websocket Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext.
    <bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>
    <bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
    

    Bean 的自动装配

    表示对象(bean)注册到容器中,交由spring托管,或者说装配

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

    spring中由三种装备方式

    1、在xml中显示的配置

    2、在Java中显示配置

    3、隐式的自动装配

    bean标签的autowird属性

    • autowird=“byName”表示自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid
    • autowird=“byType”表示自动在容器上下文中查找,和自己对象set方法后面的类型对应的beanid

    注解实现自动装配

    <!-- 导入约束,添加配置 -->
    <context:annotation-config/>
    
    • @Autowird方式:类型,名字。@Qualifier

    • java的@Resource方式:名字,类型

    • 实体类添加@Component注解即可自动装配

    • dao层使用@Repository自动装配

    • service层使用@Service自动装配

    • controller层使用@Controller自动装配

    • 需要设置作用域的话,直接加@Scope;需要注入值(赋值)的话,@Value

    xml和注解结合才是装配的最佳实践:xml用来负责管理bean、注解只负责完成属性的注入

    javaconfig方式配置spring

    @Configuration
    public class AppConfig {
        @Bean
        public MyService myService() {
            return new MyServiceImpl();
        }
    }
    

    等效于xml中的

    <beans>
        <bean id="myService" class="com.acme.services.MyServiceImpl"/>
    </beans>
    
    • @Configuration、@ComponentScan("com.hello.pojo")等注解都是都是为了替代xml配置中的那些配置项而生的

    • 如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig应用上下文来获取容器(进而getBean(方法)),通过配置类的class对象加载

    • 同样的以往xml中可以用import来引入其他xml,@Import注解同样可以引入其他配置类

    代理模式

    静态代理

    • 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务
    • 公共业务交给代理角色,实现了业务的分工
    • 公共业务需要扩展的时候,方便集中管理
    • 缺点是:一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率会变低
    //租房(抽象角色:一般使用接口或者抽象类)
    public interface Rent {
        public void rent();
    }
    //房东(真实角色:被代理的角色)
    public class Host implements Rent {
        public void rent() {
            System.out.println("本房东要出租房子了");
        }
    }
    //租客(访问代理对象的人)
    public class Client {
        public static void main(String[] args) {
            Host host = new Host();
            //host.rent();//如果我们能直接联系到房东,就可以不通过中介
            //通过代理的方式,找专业的房屋中介
            Proxy proxy = new Proxy(host);
            proxy.rent();
        }
    }
    //中介(代理角色:代理真实角色,通常会做一些附加操作)
    public class Proxy implements Rent {
    
        private Host host;
    
        public Proxy() {
        }
    
        public Proxy(Host host) {//或使用set方式注入
            this.host = host;
        }
    
        public void rent() {
            hetong();
            host.rent();
            jiaoqian();
        }
    
        public void hetong() {
            System.out.println("链家:你们两方签合同");
        }
    
        public void jiaoqian() {
            System.out.println("链家:这边把费用算一下");
        }
    }
    

    例二

    public interface UserService {
        public void add();
        public void delete();
        public void update();
        public void query();
    }
    public class UserServiceImpl implements UserService{
        public void add() {
            System.out.println("增加用户");
        }
    
        public void delete() {
            System.out.println("删除用户");
        }
    
        public void update() {
            System.out.println("更新用户");
        }
    
        public void query() {
            System.out.println("查询用户");
        }
    }
    public class Client {
        public static void main(String[] args) {
            UserServiceImpl service = new UserServiceImpl();
            //service.add();//不使用代理时
            UserServiceProxy proxy = new UserServiceProxy();
            proxy.setUserService(service);
            proxy.add();
        }
    }
    public class UserServiceProxy implements UserService {
    
        private UserServiceImpl userService;
    
        public void setUserService(UserServiceImpl userService) {
            this.userService = userService;
        }
    
        public void add() {
            log("add");
            userService.add();
        }
    
        public void delete() {
            log("delete");
            userService.delete();
        }
    
        public void update() {
            log("update");
            userService.update();
        }
    
        public void query() {
            log("query");
            userService.query();
        }
    
        public void log(String msg){
            System.out.println("[debug]使用了"+msg+"方法");
        }
    }
    

    涉及到一个背景:改动原有代码是公司中的大忌,用代理模式轻松绕开,那么完了的同时,aop也就是这个思想

    因为静态代理,这种扩展代码的方式是每次成倍增加,所以,引出一个动态代理

    动态代理

    • 基于接口的动态代理(jdk:InvocationHandler)
    • 基于类的动态代理(cglib)
    • 基于Java字节码实现:javasist

    例一

    //租房
    public interface Rent {
        public void rent();
    }
    //房东
    public class Host implements Rent {
        public void rent() {
            System.out.println("本房东要出租房子了");
        }
    }
    public class Client {
        public static void main(String[] args) {
            //真实角色
            Host host = new Host();
            //创建代理角色
            ProxyInvocationHandler handler = new ProxyInvocationHandler();
            handler.setRent(host);
            Rent proxy = (Rent) handler.getProxy();
            proxy.rent();
        }
    }
    //用这个类自动生成代理类
    public class ProxyInvocationHandler implements InvocationHandler {
    
        //被代理的接口(写成Object就通用了)
        private Rent rent;
    
        public void setRent(Rent rent) {
            this.rent = rent;
        }
    
        //生成得到代理类
        public Object getProxy() {
            return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
        }
    
        //处理代理实例 并返回结果
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            hetong();
            //动态代理的本质就是使用反射机制
            Object object = method.invoke(rent, args);
            jiaoqian();
            return object;
        }
    
        public void hetong() {
            System.out.println("链家:你们两方签合同");
        }
    
        public void jiaoqian() {
            System.out.println("链家:这边把费用算一下");
        }
    }
    

    例二

    public interface UserService {
        public void add();
        public void delete();
        public void update();
        public void query();
    }
    public class UserServiceImpl implements UserService {
        public void add() {
            System.out.println("增加用户");
        }
    
        public void delete() {
            System.out.println("删除用户");
        }
    
        public void update() {
            System.out.println("更新用户");
        }
    
        public void query() {
            System.out.println("查询用户");
        }
    }
    public class Client {
        public static void main(String[] args) {
            //真实角色
            UserServiceImpl userService = new UserServiceImpl();
            //代理角色
            ProxyInvocationHandler handler = new ProxyInvocationHandler();
            handler.setTarget(userService);//设置要代理的对象
            //动态生成代理类
            UserService proxy = (UserService) handler.getProxy();
            proxy.add();
        }
    }
    //用这个类自动生成代理类
    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);
        }
    
        //处理代理实例 并返回结果
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            log(method.getName());
            //动态代理的本质就是使用反射机制
            Object object = method.invoke(target, args);
            return object;
        }
    
        public void log(String msg){
            System.out.println("[debug]使用了"+msg+"方法");
        }
    }
    

    好处:一个动态代理类代理的是一个接口,一般就是对应的一类业务

    AOP 面向切面编程

    1. 横切关注点:跨越应用程序多个模块的方法或功能。如日志、安全、缓存、事务等等。

    2. 通知(Advice):切面的工作被称为通知。通知定义了切面是什么以及何时使用。除了描述切面要完成的工作,通知还解决了何时执行这个工作的问题(Log的方法)

      • 前置通知(Before):在目标方法被调用之前调用通知功能
      • 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么
      • 返回通知(After-returning):在目标方法成功执行之后调用通知
      • 异常通知(After-throwing):在目标方法抛出异常后调用通知
      • 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和之后执行自定义的行为
    3. 连接点(Join point):连接点是在应用执行过程中能够插入切面的一个点。

    4. 切点(Pointcut):一个切面并不需要通知应用的所有连接点,切点有助于缩小切面所通知的连接点范围。如果说通知定义了切面的“什么”和“何时”的话,那么切点就定义了“何处”。因此,切点其实就是定义了需要执行在哪些连接点上执行通知。

    5. 切面(Aspect):通知和切点的结合。通知和切点共同定义了切面的全部内容——它是什么,在何时和在何处完成其功能(Log类)

    6. 引入(Introduction):引入允许我们向现有的类添加新方法或属性。

    7. 织入(Weaving):织入是把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期中有很多个点可以进行织入:

      • 编译期:切面在目标类编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就是以这种方式织入切面的。
      • 类加载期:切面在目标类加载到JVM时被织入。这种方式需要特殊的类加载器,它可以在目标类被引入应用之前增强该目标类的字节码。AspectJ 5的加载时织入就支持这种方式织入切面。
      • 运行期:切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态的创建一个代理对象。Spring AOP就是以这种方式织入切面的。
    8. 目标对象(Target Object):被切面所通知的对象,即业务逻辑处理对象。这个对象永远是一个被代理(proxied)对象。

    9. 代理对象(Proxy Object):目标对象被切入切面之后形成的对象,从客户端看目标对象和代理对象是一样的效果。

    使用aop需要先导入织入包

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.4</version>
    </dependency>
    

    aop实现方式一

    想要切进入的内容

    public class Log implements MethodBeforeAdvice {
        //要执行的目标对象的方法 参数  目标对象
        public void before(Method method, Object[] objects, Object o) throws Throwable {
            System.out.println(o.getClass().getName()+"的"+method.getName()+"被执行了");
        }
    }
    public class AfterLog implements AfterReturningAdvice {
        //返回值
        public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
            System.out.println("执行了"+method.getName()+"方法,返回结果为:"+o);
        }
    }
    

    配置切入点

    img

    <?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
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <!--注册bean-->
        <bean id="userService" class="com.hello.service.UserServiceImpl"/>
        <bean id="log" class="com.hello.log.Log"/>
        <bean id="afterLog" class="com.hello.log.AfterLog"/>
    
        <!--方式一:使用原生spring api接口-->
        <!--需要导入aop的约束-->
        <aop:config>
            <!--要执行的位置-->
            <aop:pointcut id="pointcut" expression="execution(* com.hello.service.UserServiceImpl.*(..))"/>
            <!--执行环绕增加-->
            <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
            <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
        </aop:config>
    </beans>
    

    aop实现方式二

    (更简单)

    public class DiyPointcut {
        public void before() {
            System.out.println("方法执行前");
        }
        public void after() {
            System.out.println("方法执行hou");
        }
    }
    
    <?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
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <!--注册bean-->
        <bean id="userService" class="com.hello.service.UserServiceImpl"/>
        <bean id="log" class="com.hello.log.Log"/>
        <bean id="afterLog" class="com.hello.log.AfterLog"/>
    
        <!--方式一:使用原生spring api接口-->
        <!--需要导入aop的约束-->
            <!--要执行的位置-->
            <!--执行环绕增加-->
        <!--<aop:config>
            <aop:pointcut id="pointcut" expression="execution(* com.hello.service.UserServiceImpl.*(..))"/>
            <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
            <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
        </aop:config>-->
    
        <!--方式二:自定义类-->
        <bean id="diy" class="com.hello.diy.DiyPointcut"/>
        <aop:config>
            <!--自定义切面,ref要引用的类-->
            <aop:aspect ref="diy">
                <!--切入点-->
                <aop:pointcut id="point" expression="execution(* com.hello.service.UserServiceImpl.*(..))"/>
                <!--通知-->
                <aop:before method="before" pointcut-ref="point"/>
                <aop:after method="after" pointcut-ref="point"/>
            </aop:aspect>
        </aop:config>
    </beans>
    

    aop实现方式三

    (注解实现)

    //使用注解方式实现aop
    @Aspect //标注这个类是一个切面
    public class AnnotationPointCut {
        @Before("execution(* com.hello.service.UserServiceImpl.*(..))")
        public void before() {
            System.out.println("方法执行前");
        }
        @After("execution(* com.hello.service.UserServiceImpl.*(..))")
        public void after() {
            System.out.println("方法执行hou");
        }
        //在环绕增强中,我们可以给定一个参数,代表我们要获取处理切人的点
        @Around("execution(* com.hello.service.UserServiceImpl.*(..))")
        public void around(ProceedingJoinPoint jp) throws Throwable {
            System.out.println("环绕前");
            //Signature signature = jp.getSignature();
            //System.out.println("signature:"+signature);
            //执行方法
            Object proceed = jp.proceed();
            System.out.println("环绕后");
        }
    }
    
    <?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
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <!--注册bean-->
        <bean id="userService" class="com.hello.service.UserServiceImpl"/>
        <bean id="log" class="com.hello.log.Log"/>
        <bean id="afterLog" class="com.hello.log.AfterLog"/>
    
        <!--方式一:使用原生spring api接口-->
        <!--需要导入aop的约束-->
        <!--<aop:config>
            &lt;!&ndash;要执行的位置&ndash;&gt;
            <aop:pointcut id="pointcut" expression="execution(* com.hello.service.UserServiceImpl.*(..))"/>
            &lt;!&ndash;执行环绕增加&ndash;&gt;
            <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
            <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
        </aop:config>-->
    
        <!--方式二:自定义类-->
        <bean id="diy" class="com.hello.diy.DiyPointcut"/>
        <!--<aop:config>
            &lt;!&ndash;自定义切面,ref要引用的类&ndash;&gt;
            <aop:aspect ref="diy">
                &lt;!&ndash;切入点&ndash;&gt;
                <aop:pointcut id="point" expression="execution(* com.hello.service.UserServiceImpl.*(..))"/>
                &lt;!&ndash;通知&ndash;&gt;
                <aop:before method="before" pointcut-ref="point"/>
                <aop:after method="after" pointcut-ref="point"/>
            </aop:aspect>
        </aop:config>-->
    
        <!--方式三-->
        <bean id="annotationPointCut" class="com.hello.diy.AnnotationPointCut"/>
        <!--开启注解支持 默认jdk接口方式实现动态代理-->
        <aop:aspectj-autoproxy/>
    </beans>
    

    Spring整合Mybatis

    http://mybatis.org/spring/zh/index.html(要考虑版本)

    image-20201123112803418

    围绕着将Mybatis相关的内容交给Spring(各种配置文件的引用都是很灵活的)

    整合方式一

    将属于Mybatis的部分拆到Spring,剩下的mybatis-config.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <typeAliases>
            <package name="com.hello.pojo"/>
        </typeAliases>
    
        <!--设置setting-->
    </configuration>
    

    整合到Spring容器spring-dao.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <!--Datasource:使用spring的数据源替换mybatis的配置-->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://xxx.xxx.xxx.xxx:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;serverTimezone=UTC&amp;characterEncoding=UTF-8&amp;autoReconnect=true&amp;failOverReadOnly=false"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        </bean>
    
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <!--绑定mybatis配置文件 显然,也可以在此配置文件按中配置mybatis相关的所有配置-->
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
            <property name="mapperLocations" value="classpath:com/hello/mapper/*.xml"/>
        </bean>
    
        <!--整合方式二的话,这个也可以不要-->
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
            <!--构造器注入-->
            <constructor-arg index="0" ref="sqlSessionFactory"/>
        </bean>
    </beans>
    

    将spring-dao.xml引入到applicationContext.xml中

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <import resource="spring-dao.xml"/>
    
        <bean id="userMapper" class="com.hello.mapper.UserMapperImpl">
            <property name="sqlSession" ref="sqlSession"/>
        </bean>
    
        <bean id="userMapper2" class="com.hello.mapper.UserMapperImpl2">
            <property name="sqlSessionFactory" ref="sqlSessionFactory" />
        </bean>
    </beans>
    

    需要多出一个Impl实现类来

    /**
     * 将sqlSession私有,set注入
     * 完了去注册到spring
     */
    public class UserMapperImpl implements UserMapper {
        private SqlSessionTemplate sqlSession;
    
        public void setSqlSession(SqlSessionTemplate sqlSession) {
            this.sqlSession = sqlSession;
        }
    
        public List<User> selectUser() {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            return mapper.selectUser();
        }
    }
    

    整合方式二

    http://mybatis.org/spring/zh/sqlsession.html

    前文配置文件中已经注册

    <bean id="userMapper2" class="com.hello.mapper.UserMapperImpl2">
        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
    </bean>
    

    实现类

    public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
        public List<User> selectUser() {
            return getSqlSession().getMapper(UserMapper.class).selectUser();
        }
    }
    

    测试

    public class MyTest {
        @Test
        public void test2() throws IOException {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            UserMapper userMapper = context.getBean("userMapper2", UserMapper.class);
            for (User user : userMapper.selectUser()) {
                System.out.println(user);
            }
        }
    }
    

    配置声明式事务

    http://mybatis.org/spring/zh/transactions.html#programmatic

    spring-dao.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/tx
            https://www.springframework.org/schema/tx/spring-tx.xsd">
    
        <!--Datasource:使用spring的数据源替换mybatis的配置-->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://xxx.xxx.xxx.xxx:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;serverTimezone=UTC&amp;characterEncoding=UTF-8&amp;autoReconnect=true&amp;failOverReadOnly=false"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        </bean>
    
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <!--绑定mybatis配置文件 显然,也可以在此配置文件按中配置mybatis相关的所有配置-->
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
            <property name="mapperLocations" value="classpath:com/hello/mapper/*.xml"/>
        </bean>
    
        <!--整合方式二的话,这个也可以不要-->
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
            <!--构造器注入-->
            <constructor-arg index="0" ref="sqlSessionFactory"/>
        </bean>
    
        <!--配置声明式事务-->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
        </bean>
        <!--结合aop实现事务的织入-->
        <!--配置事务通知-->
        <tx:advice id="txAdivce" transaction-manager="transactionManager">
            <!--给哪些地方配置事务-->
            <!--配置事务的传播特性 propagation="REQUIRED"s-->
            <tx:attributes>
                <tx:method name="add"/>
                <tx:method name="delete"/>
                <tx:method name="update"/>
                <tx:method name="query"/>
                <tx:method name="*"/>
            </tx:attributes>
        </tx:advice>
        <!--配置事务切入-->
        <aop:config>
            <aop:pointcut id="txPointCut" expression="execution(* com.hello.mapper.*.*(..))"/>
            <aop:advisor advice-ref="txAdivce" pointcut-ref="txPointCut"/>
        </aop:config>
    </beans>
    
    击石乃有火,不击元无烟!!
  • 相关阅读:
    kernel 单独编译模块
    Python实现图的经典DFS、BFS、Dijkstra、Floyd、Prim、Kruskal算法
    Python实现BFS和DFS
    dpdk 20.02 igb_uio.ko 编译
    Kubernetes 文档
    controller-runtime/FAQ.md
    kubebuilder2.0学习笔记——进阶使用
    cloud-init 导致虚拟机启动太慢
    关闭 cloud-init 服务
    centos7 安装 docker calico
  • 原文地址:https://www.cnblogs.com/rain2020/p/14025432.html
Copyright © 2011-2022 走看看