Spring教程


前言


一、spring是什么

Spring是一个轻量级的控制反转(IOC)、面向切面编程(AOP)的容器。

  • 特性:控制反转,面向切面编程;
  • 支持事务处理、整合框架。

spring主要是作为springboot的基础学习的,spring中的配置文件还是很多,有些地方设置不完全。其中Bean的自动装配比较重要,对后面的学习意义重大,需要理解清楚。
另外java的反射内容需要多加理解

二、IOC

1.传统web开发

在传统的web开发过程中,实现一个业务需要一下几个部分
- XxxDao:接口
- XxxDaoImpl:接口实现类
- XxxService:业务接口
- XxxServiceImpl:业务实现类
1.UserDao

public interface UserDao {
    public void getinfo();
}

2.UserDaoImpl

public class UserDaoImpl implements UserDao{
    @Override
    public void getinfo() {
        System.out.println("user");
    }
}

3.UserService

public interface UserService {
    public void getinfo();
}

4.UserServiceImpl

public class UserServiceImpl implements UserService {
    //Service层:调用Dao层
    private UserDao userDao = new UserDaoImpl();
    @Override
    public void getinfo() {
        userDao.getinfo();
    }
}

5.Test

@Test
public void test() {
	//用户直接访问Service层,Service层调用Dao层
    UserService userService = new UserServiceImpl();
    userService.getUserInfo();
}

如果现在需要增添新用户,那么就需要在UserServiceImpl里改变相应的代码

//private UserDao userDao = new UserDaoImpl_01();
private UserDao userDao = new UserDaoImpl_02();

这样就出现了一系列问题:代码强耦合,复用性低,维护成本高。即违反了非必须不修改原代码的原则。那么我们让userDao根据set函数实现动态注入即可解决这个问题,即让程序不再有主动性,而是变成了被动的接受对象。

UserServiceImpl:

public class UserServiceImpl implements UserService {
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void getinfo() {
        userDao.getinfo();
    }
}

2.IOC本质

  1. 控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IOC的一种方法
  2. 控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。
  3. 程序员不再需要管理对象的创建,而是由用户自行根据需求选择。

3.IOC容器

在Spring中实现控制反转的是IOC容器,其工作流程有三步:

  1. Spring 容器在初始化时先读取配置文件;
  2. Spring 容器根据元数据创建并组装Bean对象;
  3. 配置好的系统程序,使用时从容器中获取需要的 Bean 对象;

三、Bean

1.概念

  1. Bean是被实例的,组装的及被Spring 容器管理的Java对象
  2. Spring容器创建、组装并管理Bean对象;
  3. 原理:通过反射实现,默认先通过无参构造创建实例,再通过getter()获取属性名,通过setter()设置属性值。

2.Bean的配置

<!--
        id:bean的唯一标识符,也就是相当于我们学的对象名
        class:bean 对象所对应的权限定名:包名 + 类型
        name: 也是别名,而且name更高级,可以起多个别名,通过逗号空格分号等分割
-->
<bean id="userT" class="pojo.User" name="user01,user02">
    <property name="name" value="username"/>
</bean>

3.依赖注入

依赖注入(Dependency Injection,DI):

  • 依赖 : 指Bean对象的创建依赖于容器 . Bean对象的依赖资源 .
  • 注入 : 指Bean对象所依赖的资源 , 由容器来设置和装配 .
  1. 构造器注入:
        <!--有参构造函数注入 -->
        <!--根据索引注入-->
        <bean id="user" class="pojo.User">
            <constructor-arg index="0" value="spring01"/>
        </bean>
        <!--根据参数名注入-->
        <bean id="user" class="pojo.User">
            <constructor-arg name="name" value="spring02"/>
        </bean>
    
  2. setter方法注入:
        <!--    
        	基本数据类型:使用value作为属性值;
            引用数据类型:使用ref作为属性值,引用容器中的其他Bean
        -->
        <!-- setter注入 重点-->
        <bean id="person" class="pojo.Person">
            <!--基本数据类型-->
            <property name="name" value="基本数据类型"/>
    
            <!--引用数据类型-->
            <property name="hello" ref="hello"/>
    
            <!--数组-->
            <property name="strings">
                <array>
                    <value>s1</value>
                    <value>s2</value>
                </array>
            </property>
    
            <!--list-->
            <property name="list">
                <list>
                    <value>"l1"</value>
                    <value>l2</value>
                </list>
            </property>
    
            <!--map-->
            <property name="map">
                <map>
                    <entry key="m1_key" value="m1_va"/>
                    <entry key="m2_key" value="m2_va"/>
                </map>
            </property>
    
            <!--set-->
            <property name="set">
                <set>
                    <value>s1</value>
                    <value>"s2"</value>
                </set>
            </property>
    
            <!--properties
            格式:key=value
            -->
            <property name="properties">
                <props>
                    <prop key="p1_key">p1_value</prop>
                    <prop key="p2_key">p2_value</prop>
                </props>
            </property>
    
            <!--null-->
            <property name="nulls">
                <null/>
            </property>
        </bean>
    

4.获取Bean

public class MyTest {
    public static void main(String[] args) {
        // 实例化容器,获取Spring的上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        //我们的对象现在都在Spring中管理了,如果要使用,直接去里面取出来就可以
        //Hello hello = (Hello)context.getBean("hello");
        Hello hello = context.getBean("hello",Hello.class);
        System.out.println(hello);
    }
}

5.Bean作用域

Spring 默认机制是省略了<bean id=“user” class=“pojo.User” scope="singleton" />,也就是我们常说也是常用的单例模式。其余几个是在Web开发中用到的
在这里插入图片描述

四、Bean自动装配

Bean自动装配的方式有三种

  1. XML 显式配置:使用配置文件;
  2. 隐式自动装配(注解):自动注入属性值
  3. Java 显式配置:实现零配置文件;

1.XMl显示配置

即上面一直在用的配置
使用 Bean 元素的 autowire 属性开启自动装配

<bean id="person" class="pojo.Person" autowire="***"/>

在这里插入图片描述

2.隐式自动装配(注解)

  1. 注解有2种类型:类级别(Component、Scope)、类内部(Autowired、Value);
  2. IOC容器会自动注册类级别注解的 Bean,前提是有context:component-scan配置支持;
  3. 要使用类内部的注解,需要有相应处理器的支持,处理器需要在 XML 中注册;
    通过context:annotation-config/标签来隐式注册处理器;
  4. 要让类级别注解生效,就要context:component-scan配置支持,而这个标签又隐式启动了context:annotation-config/;
  5. 在使用时,我们只需要引入相关配置,以及context:component-scan标签。
@Component//等价于<bean id="user" class="pojo.User"/>
/*
@Component有几个衍生的注解。按照mvc三层架构分层,这几个注解分别对应到相应的层
dao  【 @Repository 】
service  【 @Service 】
controller  【 @Controller 】
这四个注解功能都是一样的,都是代表将某个注册类注入到Spring中,装配Bean
*/
@Scope("singleton")//等价于<bean id="user" class="pojo.User" scope="singleton"/>
public class Person {

    @Autowired //引用数据类型
    @Qualifier(value="cat")
    private Cat cat;

    @Autowired
    /* 注解自动装配
        @Autowired
        工作机制:先 byType ,再 byName
        1.如果容器中只存在一个匹配的 Bean ,则自动装配
        2.如果容器中存在多个匹配的 Bean,则匹配属性名:
            a.存在与属性同名的 Bean,自动装配;
            b.不存在同名 Bean,可以添加注解 @Qualifier(value = "beanId") 来匹配 Bean
    */
    private Dog dog;

    @Value("username") //基本数据类型
    //等价于<property name="name" value="**"/>
    private String name;
    
    @Bean(value = "getUser")//默认bean名为方法名,value可以设置bean名
    public User getUser(){
        return new User();
    }

}
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

	<!--导入 context 配置-->

    <!-- 注解开发 扫描包下所有的类-->
    <context:component-scan base-package="pojo"/>

    <!-- 注解支持 -->
    <context:annotation-config/>
</beans>

3.Java 显式配置

上面的两种方法还要基于配置文件(beans.xml)来做

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Person person = context.getBean("person", Person.class);

接下来,我们可以完全不使用xml配置,全权交给java来做(这在springboot中是常见的),但是还是要利用注解

@Configuration//取代原本的 XML 配置
//被Spring容器托管,注册到容器里,因为他本来就是一个@Component(继承)
@ComponentScan(basePackages = "pojo")//相当于 XML 文件中的<context:component-scan/>标签
public class MyConfig {

    @Bean("user")
    public User getUser(){
        return new User();
    }
}
public static void main(String[] args) {
    //如果完全使用了配置类,我们就只能通过AnnotationConfig 上下文来获取容器,通过配置类的class对象加载
    ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
    User getUser = (User)context.getBean("user");
}

五、代理模式

访问对象不适合或者不能直接引用目标对象,此时给目标对象提供一个代理以控制对该对象的访问,代理模式可以起到中介和保护作用,扩展和增强目标对象的功能。

  • 静态:程序运行前。程序员在创建目标对象时创建代理类;
  • 动态:程序运行时。运用反射机制动态创建。

1.静态代理

结构说明举例
抽象主题类(Subject定义一个接口或抽象类,声明要实现的业务方法租房业务
真实主题类(Real Subject实现了抽象主题中的具体方法,是客户端最终实际访问的对象房东
代理类(Proxy实现了抽象主题类,提供一个接口来引用真实主题。
可以访问、控制和扩展真实主题的功能
房屋中介
客户端(Client通过代理,访问真实主题的业务方法找房子的人

抽象主题类(接口类):

public interface UserService {
    public void show();
}

真实主题类(接口实现类):

public class UserServiceImpl implements UserService {
    @Override
    public void show() {
        System.out.println("实现被代理对象的操作");
    }
}

代理类:

public class UserServiceProxy implements UserService {

    //静态代理
    private UserServiceImpl userService;
    public void setUserService(UserServiceImpl userService) {
        this.userService = userService;
    }
    @Override
    public void show() {
        this.doit();
        userService.show();
    }
    //实现面相切面编程
    public void doit(){
        System.out.println("实现接口操作的预操作/后续操作");
    }
}

客户端:

   UserServiceImpl userService = new UserServiceImpl();
   UserServiceProxy userServiceProxy = new UserServiceProxy();
   userServiceProxy.setUserService(userService);
   userServiceProxy.show();

2.动态代理

代理类:

//动态代理 代理的是接口实现类(不是接口类)
public class DynamicProxyHandler implements InvocationHandler {

    //被代理对象
    private Object object;

    //设置被代理对象
    public void setObject(Object object) {
        this.object = object;
    }

    //获取代理对象 根据传入的参数,通过反射生成.class
    //每一个代理对象都有一个关联的调用处理程序,当在代理对象上调用方法时,方法调用将被编码并分配到其调用处理程序的invoke方法
    public Object getProxy() {
        return Proxy.newProxyInstance(object.getClass().getClassLoader(),
                object.getClass().getInterfaces(),
                this);
    }

    //proxy 代理    method 要运行的方法   args 参数
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        pre();
        // 执行被代理对象的方法
        Object result = method.invoke(object, args);
        post();
        return result;
    }

    private void pre() {
        System.out.println("代理:预处理");
    }

    private void post() {
        System.out.println("代理:后续处理");
    }
}

客户端:

public class mytest {
    @Test
    public void fn() {
        //动态代理
        //获取被代理对象
        UserService userService = new UserServiceImpl();
        //获取处理器
        DynamicProxyHandler handler = new DynamicProxyHandler();
        //设置被代理对象
        handler.setObject(userService);
        //获取代理对象
        UserService proxy = (UserService)handler.getProxy();
        //通过代理对象访问代理对象
        proxy.show();
    }
}

六、AOP

底层实现:代理模式

1.概念

  1. AOP 是对 OOP 的补充(Object-oriented Programming,面向对象编程),并且允许自定义切面;
  2. OOP 中模块化的单位是类(Class),AOP 中模块化的单位是切面(Aspect);
  3. 切面能够实现跨类型和跨对象的横切关注点(如事务管理)的模块化;
  4. Spring IOC 容器不依赖于AOP,但 AOP 对 Spring IOC 进行了补充,提供了一个强大的中间件解决方案。

2.术语

  • 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 …
  • 切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。Log
  • 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。Log方法
  • 目标(Target):被通知对象。接口
  • 代理(Proxy):向目标对象应用通知之后创建的对象。代理类
  • 切入点(PointCut):切面通知 执行的 “地点”的定义。method
  • 连接点(JointPoint):与切入点匹配的执行点。invoke
    在这里插入图片描述

3.实现

需要导入依赖和spring配置

<dependency>
     <groupId>org.aspectj</groupId>
     <artifactId>aspectjweaver</artifactId>
     <version>1.9.7</version>
 </dependency>
 
 
 <?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"
       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
       https://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd">

方法一:使用Spring的API接口

  1. 业务接口和实现类:

    public interface UserService {
        public void add();
    }
    
    public class UserServiceImpl implements UserService{
        @Override
        public void add() {
            System.out.println(1);
        }
    }
    
  2. 增强类:

    public class Log implements MethodBeforeAdvice {
        @Override
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println(target.getClass().getName()+method.getName()+" "+this.getClass().getName());
        }
    }
    
  3. 实现aop切入实现

        <bean id="log" class="log.Log"/>
        <!--方式1:原生spring API接口-->
        <!--配置aop : 需要导入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:config>
    

方法2:自定义切面

  1. 自定义切入类:
    public class pointcut {
        public void before(){
            System.out.println("before");
        }
        public void after(){
            System.out.println("after");
        }
    }
    
  2. spring配置:
        <!--方式2:自定义-->
        <bean id="diy" class="log_div.pointcut"/>
    
        <aop:config>
            <!--自定义切面,ref:要引用的类-->
            <aop:aspect ref="diy">
                <!--切入点-->
                <aop:pointcut id="point" expression="execution(* log_div.pointcut.*(..))"/>
                <!-- 通知 -->
                <aop:before method="before" pointcut-ref="point"/>
                <aop:after method="after" pointcut-ref="point"/>
            </aop:aspect>
        </aop:config>
    

方法3:注解实现

  1. 注解实现的增强类
    @Aspect //标注这个类是个切面
    public class annotationPointcut {
    
        @Before("execution(* service.UserServiceImpl.*(..))")
        public void before() {
            System.out.println("before");
        }
    
        @After("execution(* service.UserServiceImpl.*(..))")
        public void after() {
            System.out.println("after");
        }
    
        @Around("execution(* service.UserServiceImpl.*(..))")
        public void around(ProceedingJoinPoint joinPoint) {
            System.out.println("around before");
    
            //连接点签名(方法)
            Signature signature = joinPoint.getSignature();
            System.out.println(signature);
    
            //运行连接点方法(目标对象本身的方法)
            try {
                joinPoint.proceed();
            } catch (Throwable e) {
                e.printStackTrace();
            }
            
            System.out.println("around after");
        }
    }
    
  2. spring配置
        <!--方式3:注解实现-->
        <bean id="annotationPointcut" class="log_div.annotationPointcut"/>
        <!--开启注解支持-->
        <aop:aspectj-autoproxy/>
    

七、整合Mybatis

pom.xml

 <dependencies>
     <!-- MyBatis -->
     <dependency>
         <groupId>org.mybatis</groupId>
         <artifactId>mybatis</artifactId>
         <version>3.5.6</version>
     </dependency>

     <!-- 数据库连接 -->
     <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
         <version>5.1.46</version>
     </dependency>

     <!-- MyBatis整合Spring -->
     <dependency>
         <groupId>org.mybatis</groupId>
         <artifactId>mybatis-spring</artifactId>
         <version>2.0.6</version>
     </dependency>

     <!-- AOP 织入器 -->
     <dependency>
         <groupId>org.aspectj</groupId>
         <artifactId>aspectjweaver</artifactId>
         <version>1.9.7</version>
     </dependency>

     <!--spring-webmvc-->
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-webmvc</artifactId>
         <version>5.3.9</version>
     </dependency>
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-jdbc</artifactId>
         <version>5.3.9</version>
     </dependency>

 </dependencies>

 <build>
     <resources>
         <resource>
             <directory>src/main/java</directory>
             <includes>
                 <include>**/*.properties</include>
                 <include>**/*.xml</include>
             </includes>
         </resource>
         <resource>
             <directory>src/main/resources</directory>
             <includes>
                 <include>**/*.properties</include>
                 <include>**/*.xml</include>
             </includes>
         </resource>
     </resources>
 </build>

1. 方式一(SqlSessionTemplate)

mybatis-spring.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
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd">


    <!-- 数据源 -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url"
                  value="jdbc:mysql://localhost:3306?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value="20010823GTH"/>
    </bean>

    <!-- sqlSessionFactory
        1、可以实现mybatis-config中所有的配置,取代mybatis-config的工作;
        2、也可以绑定 mybatis-config ,二者同时存在
    -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- 绑定MyBatis配置文件 -->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!-- 注册Mapper  也可以放到mybatis-config.xml里面-->
        <property name="mapperLocations" value="classpath:dao/UserMapper.xml"/>
    </bean>

    <!--SqlSessionTemplate
        类似MyBatis中的SqlSession,
    -->
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <!--没有setter,只能通过构造器注入(只有一个参数)-->
        <constructor-arg ref="sqlSessionFactory"/>
    </bean>

</beans>

UserMapperImpl

public class UserMapperImpl implements UserMapper{
     //SqlSessionTemplate:获取Mapper接口,执行方法
    private SqlSessionTemplate sqlSession;

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

    @Override
    public List<User> getUserList() {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        return mapper.getUserList();
    }
}

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

    <!--合并其他配置文件,作为Spring 总配置-->
    <!--导入的配置文件专门用于处理某项功能,分工明确-->
    <!--1.有关 MyBatis 的配置都在mybatis-spring.xml中完成-->
    <!--2.在 applicationContext 中注册 Bean-->
    <import resource="mybatis-spring.xml"/>

    <!-- Mapper接口实现类 -->
    <!--方式1-->
    <bean id="userMapper" class="dao.UserMapperImpl">
        <property name="sqlSession" ref="sqlSessionTemplate"/>
    </bean>

</beans>

2.方式二(SqlSessionDaoSupport)

mybatis-spring.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
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd">


    <!-- 数据源 -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url"
                  value="jdbc:mysql://localhost:3306?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value="20010823GTH"/>
    </bean>

    <!-- sqlSessionFactory
        1、可以实现mybatis-config中所有的配置,取代mybatis-config的工作;
        2、也可以绑定 mybatis-config ,二者同时存在
    -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- 绑定MyBatis配置文件 -->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!-- 注册Mapper  也可以放到mybatis-config.xml里面-->
        <property name="mapperLocations" value="classpath:dao/UserMapper.xml"/>
    </bean>
</beans>

UserMapperImpl

public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{
    @Override
    public List<User> getUserList() {
        return getSqlSession().getMapper(UserMapper.class).getUserList();
    }
}

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

    <!--合并其他配置文件,作为Spring 总配置-->
    <!--导入的配置文件专门用于处理某项功能,分工明确-->
    <!--1.有关 MyBatis 的配置都在mybatis-spring.xml中完成-->
    <!--2.在 applicationContext 中注册 Bean-->
    <import resource="mybatis-spring.xml"/>

    <!-- Mapper接口实现类 -->
    <!--方式2-->
    <bean id="userMapper02" class="dao.UserMapperImpl02">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
</beans>

八、事务管理

  1. 编程式事务:需要在代码中,进行事务的管理
    - 将事务管理代码嵌到业务方法中来控制事务的提交和回滚
    - 缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码
  2. 声明式事务:AOP
    - 一般情况下比编程式事务好用。
    - 将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。
    - 将事务管理作为横切关注点,通过aop方法模块化。

总结

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值