Spring基础、IOC、AOP、设计模式、Spring+MyBatis、事务、注解开发、Junit

文章目录

一、前言

1.1原生web开发中存在哪些问题?

· 传统web开发存在硬编码所造成的过度程序耦合(例如:Service中作为属性Dao对象)。
· 部分JavaEE API较为复杂,使用效率低(例如:JDBC开发步骤)。
· 侵入性强,移植性差(例如:DAO实现的更换,从Connection到SqlSession)。

二、Spring框架

2.1概念

· Spring是一个项目管理框架,同时也是一套Java EE解决方案。
· Spring是众多优秀设计模式的组合(工厂、单例、代理、适配器、包装器、观察者、模板、策略)。
· Spring 并未替代现有框架产品,而是将众多框架进行有机整合,简化企业开发,俗称“胶水框架”‘。

2.2访问与下载

官方网站:http://spring.io/
下载地址:https://repo.spring.io/release/org/springframework/spring

三、Spring架构组成

Spring架构由诸多模块组成,可分类为:
	1、核心技术:**依赖注入**、事件、资源、验证、数据绑定、类型转换、SpEL、**AOP**。
	2、测试:;模拟对象、TestContext框架,Spring MVC测试、WebTestClient。
	3、数据访问:事务,DAO支持,JDBC、ORM、封送XML
	4、Spring MVC和Spring web Flux Web框架。
	5、集成:远程处理,JMS,JCA,JMX,电子邮件,任务,调度,缓存。
	6、语言:Kotlin,Groovy,动态语言。

在这里插入图片描述

四、自定义工厂

4.1配置文件(bean.properties)

1、userDao=cn.kgc.dao.UserDaoImpl
2、userService=cn.kgc.service.UserServiceImpl

4.2工厂类

//工厂类    1、加载配置文件    2、生产配置中记录的对应对象
public class MyFactory {
    private Properties properties = new Properties();

    public MyFactory(){}

    public MyFactory(String config) throws IOException {
        InputStream resourceAsStream = MyFactory.class.getResourceAsStream(config);
        properties.load(resourceAsStream);//读取配置文件 properties
    }
       //获取对象
    public  Object getBean(String name) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        //1、通过那么,获取对应类路径
        String classPath = properties.getProperty(name);
        if(classPath!=null){
            Class claz = null;
            //2、反射   构建对象
            Class claz = Class.forName(classPath);
            return claz.newInstance();
        }
      return  null;
    }
}

五、Spring环境搭建

5.1 pom.xml中引入Spring常用依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>spring_demo_01</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
    	<!--Spring依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
    </dependencies>
</project>

5.2创建Spring配置文件

命名无限制,约定俗成命名由:Spring-context.xml、applicationContext.xml、beans.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/tx/spring-tx-2.5.xsd">
	 <!--要工厂生产的对象-->
	<bean id="userDao" class="cn.kgc.dao.UserDaoImpl"></bean>
    <bean id="userService" class="cn.kgc.service.UserServiceImpl"></bean>
 </beans>

5.3 Spring工厂

public class SpringFactory {
    @Test
    public void testSpringFactory(){
        //启动工厂
        ApplicationContext context = new ClassPathXmlApplicationContext("/spring-context.xml");
        //获取对象,相当于我们之前硬编码的创建对象,现在交由Spring处理
        UserDao userDao = (UserDao) context.getBean("userDao");
        UserService userService = (UserService)context.getBean("userService");

        userDao.delUser(1);
        userService.delUser(2);
    }
}

六、依赖与配置文件详解

Spring框架包含多个模块,每个模块各司其职,可结合需求引入相关依赖jar包实现功能。

6.1 Spring依赖关系

在这里插入图片描述

6.2 schema

配置文件中的顶级标签中包含了语义化标签的相关信息
	·xmlns:语义化标签所在的命名空间。
	xmlns:xsi:XMLSchema-instance标签遵循Schema标签标准。
	xsi:schemaLocation:xsd文件位置,用以描述标签语义、属性、取值范围等。

七、IoC(Inversion of Control)控制反转【重点】

**Inversion of Control:**控制反转
反转了依赖关系的能满足方式,由之前的自己创建依赖对象,变为由工厂推送。(变主动为被动,即反转)
解决了具有依赖关系的组件之间的强耦合,是的项目形态更加稳健

7.1 项目中的强耦合问题

public class UserDaoImpl implements UserDao {
    public void delUser(Integer id) {
        System.out.println("删除id为"+id+"的user in dao!");
    }
}
public class UserServiceImpl implements UserService  {
    //强耦合了UserDaoImpl,使得UserServiceImpl变得不健壮
    private UserDao userDao = new UserDaoImpl();
    public void delUser(Integer id) {
        userDao.delUser(id);
    }

}

7.2解决方案

//不引用任何一个具体的组件(实现类),在需要其他组件的位置预留存取值入口(set/get)
public class UserServiceImpl implements UserService  {
    //不再耦合任何Dao实现,消除不稳健因素
    private UserDao userDao;
	//为userDao定义set/get,允许userDao属性接受spring赋值
	//Getters  and  Setters
    public void delUser(Integer id) {
        userDao.delUser(id);
    }
	
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

    <bean id="userDao" class="cn.kgc.dao.UserDaoImpl"></bean>
    <bean id="userService" class="cn.kgc.service.UserServiceImpl">
        <!--userDao属性赋值,值是id为userDao的bean-->
        <property name="userDao" ref="userDao"/>
    </bean>

如果此时需要更换UserDao实现类,则UserServiceImpl不用任何改动!,则此时的UserServiceImpl组件变得更加稳健!

八、DI(Dependency Injection)依赖注入【重点】

8.1概念

在Spring创建对象的同时,为其属性赋值,称之为依赖注入。

8.2 set注入

创建对象时,Spring工厂会通过Set方法为对象的属性赋值。

8.2.1 定义目标Bean类型

public class User implements Serializable {
    private Integer id;
    private String name;
    private String password;
    private Status status;//自建类型
    private Date bornDate;
    private String[] hobbys;
    private Set<String> phones;
    private List<String> names;
    private Map<String,String> countries;
    private Properties files;
	//Getter/Setter
public class Status implements Serializable {
    private Integer id;
    private String status;
//Getter/Setter
}

8.2.2 基本类型+字符串类型+日期类型

<!--简单:JDK8种基本数据类型-->
        <property name="id" value="10"/>
        <property name="name" value="liwang"/>
        <property name="password" value="123456"/>
        <property name="bornDate" value="2020/12/11"/>

8.2.3 容器类型

<!--数组-->
        <property name="hobbys">
            <array>
                <value>football</value>
                <value>basketball</value>
            </array>
        </property>
<!--集合-->
        <property name="phones">
            <set>
                <value>1111111</value>
                <value>2222222</value>
            </set>
        </property>
        <property name="names">
            <list>
                <value>tom</value>
                <value>jack</value>
            </list>
        </property>
        <property name="countries">
            <map>
                <entry key="zh" value="china"/>
                <entry key="en" value="english"/>
            </map>
        </property>
        <property name="files">
            <props>
                <prop key="url">jdbc:mysql:XXX</prop>
                <prop key="username">root</prop>
            </props>
        </property>

8.2.4自建类型

<!--次要bean,被作为属性-->
	<bean id="sta" class="cn.kgc.pojo.Status">
        <property name="id" value="1"/>
        <property name="status" value="管理员"/>
    </bean>
<!--主要bean,操作的主体-->
<bean id="user" class="cn.kgc.pojo.User">
	 <property name="status" ref="sta"/>
</bean>
<!--次要bean,被作为属性-->
    <bean id="userDao" class="cn.kgc.dao.UserDaoImpl"></bean>
<!--主要bean,操作的主体-->
<bean id="userService" class="cn.kgc.service.UserServiceImpl">
        <!--userDao属性赋值,值是id为userDao的bean
        注入:属性值   依赖关系
        -->
        <property name="userDao" ref="userDao"/>
</bean>

8.3 构造注入【了解】

创建对象时,spring工厂会通过构造方法为对象的属性赋值

8.3.1 定义目标Bean类型

public class Student {
    private Integer id;
    private String name;
    private String sex;
    private Integer age;
    //Constructors
    public Student(Integer id, String name, String sex, Integer age) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
}

8.3.2 注入

 <!--构造注入-->
    <bean id="student" class="cn.kgc.pojo.Student">
        <constructor-arg name="id" value="1"/>
        <constructor-arg name="name" value="liwang"/>
        <constructor-arg name="sex" value=""/>
        <constructor-arg name="age" value="22"/>
    </bean>

8.4 自动注入【了解】

autowire:默认是byType
<!--注解注入 byName-->
    <bean id="userDao" class="cn.kgc.dao.UserDaoImpl"/>
    <bean id="userService" class="cn.kgc.service.UserServiceImpl" autowire="byName"/>
public class UserServiceImpl implements UserService  {
    //强耦合了UserDaoImpl,使得UserServiceImpl变得不健壮
    private UserDao userDao;


    public void delUser(Integer id) {
        System.out.println("service中");
        userDao.delUser(id);
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

九、Bean细节

9.1控制简单对象的单例、多例模式

配置<bean scope="singleton | prototype"/>

``xml

``` 注意:需要根据场景决定对象的单例、多例模式。 可以共用:Service、Dao、SqlSessionFactory(或者是所有的工厂) 不可共用:Connection、SqlSession、ShoppingCart。

9.2 FactoryBean创建复杂对象【了解】

作用:让Spring可以创建复杂对象,或者无法直接通过反射创建的对象 

9.2.1 实现factoryBean接口

//需要添加mysql的依赖
public class MyConnectionFactoryBean implements FactoryBean<Connection> {
    public Connection getObject() throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        return DriverManager.getConnection("jdbc:mysql://localhost:3306/member","root","root");
    }

    public Class<?> getObjectType() {
        return Connection.class;
    }

    public boolean isSingleton() {
        return false;
    }
}

9.2.2配置spring-context.xml

    <!--Connection
        SqlSessionFactory
        复杂对象
        FactoryBean
        当从工厂索要一个bean时,如果是Factory,
        实际返回的是工厂Bean的getObject方法的返回值 如果要返回工厂就要在getBean("&conn")
    -->
    <bean id="conn" class="cn.kgc.factorybean.MyConnectionFactoryBean"/>

十、Spring工厂特性

10.1 饿汉模式创造优势

工厂创建之后,会将Spring配置文件中的所有对象都创建完成(饿汉式)。
提高程序运行效率。避免多次IO,减少对象创建时间。(概念接近连接池,一次性创建好,使用时直接获取)

10.2 生命周期方法

1、自定义初始化方法:添加“init-method”属性,Spring则会在创建对象之后,调用此方法。
2、自定义销毁方法:添加“destroy-method”属性,spring则会在销毁对象之前,调用此方法。
3、销毁:工厂的close()方法被调用之后,Spring会毁掉所有已创建的单例对象。
4、分类:Singleton对象由Spring容器销毁、Prototype对象由JCM销毁

10.3 生命周期注解

初始化注解、销毁注解
//后处理器
//构造、set、init、destroy
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("后处理器在init之前执行:"+bean+"    :"+beanName);
        return bean;
    }
    /**
     * 在bean的init方法执行后
     * @param bean postProcessBeforeInitialization返回bean
     * @param beanName
     * */
   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
       System.out.println("后处理器在init之后执行"+bean+"     :"+beanName);
        return bean;//此处返回的是getBean()最终的返回值
    }
}

10.4 生命周期阶段

单例bean:singleton
随着工厂启动创建==》构造方法==》set方法(注入值)init(初始化)==》构建完成==》随工厂关闭销毁
多例bean:prototype
被使用时创建==》构造方法==》set方法(注入值)==》init(初始化)==》构建完成==》JVM垃圾回收销毁

十一、代理设计模式

11.1概念

将核心功能与辅助功能(事务、日志、性能监控代码)分离,达到核心业务功能更纯粹、辅助业务功能可复用

在这里插入图片描述

11.2 静态代理设计模式

通过代理类的对象,为原始类的对象(目标类的对象)添加辅助功能,更容易更换代理实现类、力与维护

在这里插入图片描述
· 代理类=实现原始类相同接口+添加辅助功能+调用原始类的业务方法。
·静态代理问题:
代理类数量过多,不利于项目管理。
多个代理类的辅助功能代码冗余,维护性差。

11.3 动态代理设计模式

动态创建代理类的对象,为原始类的对象添加辅助功能。

11.3.1JDK动态代理实现(基于接口)

在这里插入图片描述

11.3.2 CGlib动态代理实现(基于继承)

在这里插入图片描述

十二、面向切面编程【重点】

12.1概念

AOP(Aspect Oriented Programming)即面向切面编程,利用一种称为“横切”的技术,剖开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为“Aspect”,即切面。所谓“切面”,简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

12.2 AOP开发术语

1、连接点(Joinpoint):连接点时程序类中客观存在的方法,可被Spring拦截并切入内容。
2、切入点(Pointcut):被Spring切入连接点。
3、通知、增强(Advice):可以为切入点添加额外功能,分为:前置通知、后置功能、异常通知、环绕通知等。
4、目标对象(Target):代理的目标对象
5、引介(Introduction):一种特殊的增强,可在运行期间为类动态添加Field和Method。
6、织入(Weaving):把通知应用到具体的类,进而创建新的代理类的过程。
7、代理(Proxy):被AOP织入通知后,产生的结果类。
8、切面(Aspect):由切点和通知组成,将横切逻辑织入切面所制定的连接点中

作用

Spring的AOP编程即是通过动态代理类为原始类的方法添加辅助功能。

12.4 环境搭建

引入AOP相关依赖
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.1.6.RELEASE</version>
</dependency>
<!--spring-context.xml引入AOP命名空间-->
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xmlns:tx="http://www.springframework.org/schema/tx"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
	   			http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context.xsd
                http://www.springframework.org/schema/tx
                http://www.springframework.org/schema/tx/spring-tx.xsd
				http://www.springframework.org/schema/aop
				http://www.springframework.org/schema/aop/spring-aop.xsd
">

12.5 开发流程

定义原始类
public interface UserService {
    //查询
    public List<User> queryUsers();
}
public class UserServiceImpl implements UserService {
    public void queryUsers() {
        System.out.println("查询User");
    }
}
//定义通知类(添加额外功能)
public class MyAdvice {
    //前置通知
    public void before(JoinPoint a) throws Throwable {
        System.out.println("前置通知!");
    }
    //后置通知
    public void afterReturning(JoinPoint a,Object ret) throws Throwable {
        System.out.println("后置通知");
    }
    //环绕通知
    public Object invoke(ProceedingJoinPoint p) throws Throwable {
        System.out.println("环绕开始。。。。");
        Object proceed = p.proceed();
        System.out.println("环绕结束");
        return proceed;
    }
    //异常通知
    public void afterThrowing(JoinPoint a,Exception ex){
        System.out.println("异常通知");
    }
}
<!--定义切入点(PointCut)    形成切面-->
	<aop:config>
	<!--切点-->
		<aop:pointcut id="pc_tx" expression="execution(* cn.kgc.service.UserServiceImpl.*(..))"/>
		<!--组装切面-->
		<aop:advisor advice-ref="interceptor" pointcut-ref="pc_tx"/>
	</aop:config>

12.6 AOP小结

1、通过AOP提供的编码流程,更便利的定制切面,更方便的定制了动态代理。
2、进而彻底解决了辅助功能冗余的问题;
3、业务类中职责单一性得到更好保障;
辅助功能也有很好的复用性。

12.7通知类

定义通知类,达到通知效果
	1、前置通知:MethodBefore'Advice
	2、后置通知:AfterAdvice
	3、异常通知:ThrowsAdvice
	4、环绕通知:MethodInterceptor

12.8 通配切入点

根据表达式通配切入点
 <!--以携带参数为-->
        <aop:pointcut id="pc01" expression="execution(* *(cn.kgc.pojo.User))"/>
        <!--任意没有参数的方法-->
        <aop:pointcut id="pc02" expression="execution(* *())"/>
        <!--方法名为savaUser,参数随意-->
        <aop:pointcut id="pc03" expression="execution(* savaUser(..))"/>
        <!--返回值为User,但是方法名和参数是任意的-->
        <aop:pointcut id="pc04" expression="execution(cn.kgc.pojo.User *(..))"/>
        <!--指定类下的所有方法-->
        <aop:pointcut id="pc05" expression="execution(* cn.kgc.service.UserServiceImpl.*(..))"/>
        <!--指定包下的的所有类中的方法-->
        <aop:pointcut id="pc06" expression="execution(* cn.kgc.service.*.*(..))"/>
        <!--指定cn包下的所有类和其下的所有子包中的类的方法-->
        <aop:pointcut id="pc07" expression="execution(* cn..*.*(..))"/>

12.9 JDK和CGLIB选择

1、spring底层,包含jdk代理和cglib代理两种动态代理生成机制
2、基本规则是:目标业务类如果有接口则用JDK代理,没有接口则用CGLIB代理
class DefaultAopProxyFactory{
	//该方法中明确定义了  JDK代理和CGLIB代理的选取规则
	//基本规则是:目标业务类如果有接口则用JDK代理,没有接口则用CGLIB代理
	public AopProxy createAopProxy(){...}
}

十三、Spring+MyBatis 【重点】

13.1 配置数据源

将数据配置到项目中

13.1.1 引入jdbc.properties配置文件

#db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/students?characterEncoding=utf-8
user=root
password=root

13.1.2 整合Spring配置文件和properties配置文件

<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xmlns:tx="http://www.springframework.org/schema/tx"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
	   			http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context.xsd
                http://www.springframework.org/schema/tx
                http://www.springframework.org/schema/tx/spring-tx.xsd
				http://www.springframework.org/schema/aop
				http://www.springframework.org/schema/aop/spring-aop.xsd
">

		<!--配置文件参数化(参数占位符)-->
		<context:property-placeholder location="classpath:db.properties"/>
		<!--与pooledDataSource集成     [二选一]-->
		<bean id="dataSource" class="org.apache.ibatis.datasource.pooled.PooledDataSource">
			<property name="driver" value="${driver}"/>
			<property name="url" value="${url}"/>
			<property name="username" value="${user}"/>
			<property name="password" value="${password}"/>
 		</bean>
		<!--与DruidDataSource集成    [二选一]-->
		<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
			<!--基本配置-->
			<property name="driverClassName" value="${driver}"/>
			<property name="url" value="${url}"/>
			<property name="username" value="${user}"/>
			<property name="password" value="${password}"/>

			<!--配置初始化大小、最小、最大-->
			<property name="initialSize" value="${jdbc.initialPoolSize}"/>
			<property name="minIdle" value="${jdbc.minPoolSize}"/>
			<property name="maxActive" value="${jdbc.maxPoolSize}"/>
			<!--配置获取连接等待超时的时间-->
			<property name="maxWait" value="60000"/>
			<!--配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒-->
			<property name="timeBetweenEvictionRunsMillis" value="60000"/>
			<!--配置一个连接在池中最小生存的时间,单位是毫秒-->
			<property name="minEvictableIdleTimeMillis" value="30000"/>
 		</bean>
</beans>

13.1.3Druid连接池可选参数

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
			<!--基本配置-->
			<property name="driverClassName" value="${driver}"/>
			<property name="url" value="${url}"/>
			<property name="username" value="${user}"/>
			<property name="password" value="${password}"/>

			<!--配置初始化大小、最小、最大-->
			<property name="initialSize" value="${jdbc.initialPoolSize}"/>
			<property name="minIdle" value="${jdbc.minPoolSize}"/>
			<property name="maxActive" value="${jdbc.maxPoolSize}"/>
			<!--配置获取连接等待超时的时间-->
			<property name="maxWait" value="60000"/>
			<!--配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒-->
			<property name="timeBetweenEvictionRunsMillis" value="60000"/>
			<!--配置一个连接在池中最小生存的时间,单位是毫秒-->
			<property name="minEvictableIdleTimeMillis" value="30000"/>
 		</bean>

13.2整合MyBatis

将SqlSessionDFactory、Dao、Service配置到项目中

13.2.1 导入依赖

    <!--将Mybatis与Spring进行整合-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.1</version>
    </dependency>
     <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>4.3.18.RELEASE</version>
    </dependency>

13.2.2 配置SqlSessionFactory

<!--生产一个SqlSessionFactory-->
		<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
			<!--注入连接池-->
			<property name="dataSource" ref="dataSource"/>
			<!--注入dao-mapper文件信息,如果映射文件和dao接口同包且同名,则此配置可以省略-->
			<property name="mapperLocations">
				<list>
					<value>cn/kgc/dao/UserDaoMapper.xml</value>
				</list>
			</property>
			<!--为dao-mapper文件中的实体  定义缺省包路径
			如:<select id="queryAll" resultType="User">中User类可以不定义包
			-->
			<property name="typeAliasesPackage" value="cn.kgc.pojo"/>
		</bean>

13.2.3 配置MapperScannerConfigurer

管理Dao实现类的创建,并创建Dao对象,存入工厂管理
	1、扫描所有Dao接口,去构建Dao实现
	2、将Dao实现存入工厂管理
	3、Dao实现对象在工厂中的id是:“首字母小写-接口的类名”,
		例如:UserDao===》userDao,OrderDao===》orderDao
<!--mapperScannerConfigurer映射器,相当于自动实现dao实现类-->
		<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
			<!--dao接口所在的包   如果有多个包,可以用逗号或分号分隔-->
			<property name="basePackage" value="cn.kgc.dao"/>
			<!--如果工厂中只有一个SqlSessionFactory的bean,此配置可省略-->
			<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
 		</bean>

13.2.4 配置Service

	<bean id="userService" class="cn.kgc.service.UserServiceImpl">
		<property name="userDao" ref="userDao"/>
 	</bean>

十四、事务

14.1配置DataSourceTransactionManager

事务管理器,其中持有DataSource,可以控制事务(commit、rollback等)
<!--引入一个事务管理器,其中依赖dataSource,介意获得连接,进而控制事务逻辑-->
	<bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>

**注意:**DataSourceTransactionManager和SqlSessionFactoryBean要注入同一个DataSource的Bean,否则事务控制失败!!!

14.2 配置事务通知

基于事务管理器,进一步定制,生成一个额外功能:Advice。
此Advice可以切入任何需要事物的方法,通过事务管理器为方法控制事务。
<tx:advice id="interceptor" transaction-manager="tx">
		<tx:attributes>
			<!--针对具体的方法,采用对应事务实行-->
			<!--<tx:method name="addUser" rollback-for="Exception" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>-->
			<!--以User结尾的方法,切入此方法时,采用对应事务实行-->
			<tx:method name="*User" rollback-for="Exception"/>
			<!--以query开头的方法,切入此方法时,采用对应事务实行-->
			<tx:method name="query*" propagation="SUPPORTS"/>
			<!--剩余所有方法-->
			<tx:method name="*"/>
		</tx:attributes>
	</tx:advice>

14.3事务属性

14.3.1隔离级别

14.3.1.1 概念
isolation   隔离级别
名称描述
default(默认值)采用数据库的默认设置
read-uncommited度未提交
read-commited都提交(Oracle数据库默认的隔离级别)
repeatable-read可重复读(mysql数据库默认的隔离级别)
seralized-read序列化

隔离级别由低到高为: read-uncommited < read-commited < repeatable-read < seralized-read

14.3.1.2 特性
1、安全性:级别越高,多事务并发时,越安全。因为共享的数据越来越少,十五件彼此干扰减少。
2、并发性:级别越高,多事务并发时,并发越差。因为共享的数据越来越少,事务间阻塞情况增多。
14.3.1.3 并发问题
事务并发时的安全问题

在这里插入图片描述

14.3.2 传播行为

propagation   传播行为
当涉及到事务嵌套(Service调用Service)时,可以设置:
	1、SUPPORTS = 不存在外部事务,则不开启新事务;存在外部事务,则合并到外部事务中(适合查询)
	2、REQUIRED = 不存在外部事务,则开启新事务;存在外部事务,则合并到外部事务中(适合增删改)

14.3.3读写性

readonly 读写性
1、true:只读,可以提高查询效率(适合查询)
2、false:可读可写。默认值(蛇和增删改)

14.3.4 事务超时

timeout 事务超时时间
当事务所需操作的数据被其他事务占用,则等待。
100:自定义等待时间100(秒)
-1:由数据库指定等待时间,默认值。

14.3.5 事务回滚

rollback-for   会回滚事务
1、如果事务中抛出RuntimeException,则自动回滚
2、如果事务中抛出CheckException(非运行时异常Exception),不会自动回滚,而是默认提交事务
3、处理方案:将CheckException转换成RuntimeException上跑,或设置rollback-for="Exception"

14.4 编织

将事务管理的Advice切入需要事务的业务方法中
<aop:config>
		<aop:pointcut id="pc_tx" expression="execution(* cn.kgc.service.UserServiceImpl.*(..))"/>
		<!--组织切面-->
		<aop:advisor advice-ref="interceptor" pointcut-ref="pc_tx"/>

十五、注解开发

15.1声明bean

用于替换自建类型组件的<bean...>标签;可以更快速的声明bean
1、@Service业务类专用   @Repository  dao实现类专用  @Controller  web层专用
2、@Component 通用
3、@Scope用户控制bean的创建模式
//@Service     //相当于   <bean id="userServiceImpl" class="XX.XX.XX.UserServiceImpl"></bean>
@Service("userService2") //相当于   <bean id="userServiceI" class="XX.XX.XX.UserServiceImpl"></bean>
@Scope("singleton")//声明创建摩士,默认为单例模式; @Scope("prototype"),设置成多例模式
//类中的每个方法都切入事务(有自己的事务控制的方法除外)
@Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,readOnly = false,rollbackFor = Exception.class,timeout = -1)
public class UserServiceImpl implements UserService {
    //@Autowired   类型  自动注入
    //@Resource //名称  自动注入
    //基于类型自动注入,并挑选beanid="userDao"
    @Autowired
    @Qualifier("userDao")
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    @Transactional(propagation = Propagation.SUPPORTS)//该方法自己的事务控制,仅对此方法有效
    public List<User> queryUsers() {
        return userDao.queryUsers();
    }
}

15.2 注入(DI)

用于完成bean中属性值的注入
	1、@Autowired基于类型自动注入
	2、@Resource基于名称自动注入
	3、@Qualifier("userDao")限定要自动注入的bean的id,一般和@Autowired联用
	4、@value注入简单类型数据(jdk8种+String)

15.3 事务控制

用于控制事务切入
	1、@Transactional
	2、工厂配置中的<tx:advice.....>和<aop:config...>可以省略
//类中的每个方法都切入事务(有自己的事务控制的方法除外)
@Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,readOnly = false,rollbackFor = Exception.class,timeout = -1)
public class UserServiceImpl implements UserService {
    @Transactional(propagation = Propagation.SUPPORTS)//该方法自己的事务控制,仅对此方法有效
    public List<User> queryUsers() {
        return userDao.queryUsers();
    }

15.4 注解所需配置

<!--告知spring注解位置-->
	<context:component-scan base-package="cn.kgc"></context:component-scan>
	<!--@Transational注解启动-->
	<tx:annotation-driven transaction-manager="tx"/>

15.5AOP开发

15.5.1注解使用

package cn.kgc.advice;

import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.aop.ThrowsAdvice;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
@Aspect    //声明此类是一个切面类,会包含切入点(pointcut)和通知(advice)
@Component    //声明组件,进入工厂
public class MyAdvice {
    //定义切入点
    @Pointcut("execution(* cn.kgc.service.UserServiceImpl.*(..))")
    public void pc(){}
    //前置通知
    @Before("pc()")
    public void before(JoinPoint a) throws Throwable {
        System.out.println("前置通知!");
    }
    //后置通知
    @AfterReturning(value = "pc()",returning = "ret")
    public void afterReturning(JoinPoint a,Object ret) throws Throwable {
        System.out.println("后置通知");
    }
    //环绕通知
    @Around(("pc()"))
    public Object invoke(ProceedingJoinPoint p) throws Throwable {
        System.out.println("环绕开始。。。。");
        Object proceed = p.proceed();
        System.out.println("环绕结束");
        return proceed;
    }
    //异常通知
    @AfterThrowing(value = "pc()",throwing = "ex")
    public void afterThrowing(JoinPoint a,Exception ex){
        System.out.println("异常通知");
    }
}

15.5.2 配置

	<!--添加如下配置    启用aop注释-->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

十六、集成JUnit

16.1 导入依赖

 <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>4.3.6.RELEASE</version>
    </dependency>
     <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
    </dependency>

16.2 编码

可以免去工厂的创建过程;
可以直接将要测试的组件注入到测试类。
//测试启动   启动spring工厂   并且当前测试类也会被工厂生产
@RunWith(SpringJUnit4ClassRunner.class)//负责启动
@ContextConfiguration("classpath:applicationContext.xml")//负责制定配置文件位置
public class TestSpringMyBatis {

    @Autowired
    @Qualifier("userService2")
    private UserService userService;

    @Autowired
    private SqlSessionFactory factory;
    @Test
    public void testSpringJunit(){
       /* List<User> users = userService.queryUsers();
        for (User user : users) {
            System.out.println(user.toString());
        }*/
        SqlSession sqlSession = factory.openSession();
        UserDao mapper  = sqlSession.getMapper(UserDao.class);
        List<User> users = mapper.queryUsers();
        for (User user : users) {
            System.out.println(user.toString());
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值