0
点赞
收藏
分享

微信扫一扫

07JavaEE第七章spring

Yaphets_巍 2022-03-13 阅读 75

Spring 是什么?

Spring 是于 2003 年兴起的一个轻量级的,IOC 和 AOP 的 Java 开发框架,它是为了简化企业级应用开发而生的。

Spring 优点

轻量级的

Spring 框架使用的 jar 都比较小,一般在 1M 以下或者几百 kb。Spring 核心功能的所需的 jar 总共在 3M 左右。 Spring 框架运行占用的资源少,运行效率高。

非侵入式

编写一些业务类的时候不需要继承 spring 特定的类,通过配置完成依赖注入后就可以使用,此时,spring 就没有侵入到我业务类的代码里.

IOC

即 Inversion of Control,缩写为 IOC,就是由 Spring IoC 容器管理对象,而非传统实现中由程序代码直接操控.

AOP

通过 Spring 提供的 AOP 功能,方便进行面向切面的编程,许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松应付在 Spring 中,开发人员可以从繁杂的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。

一站式框架

Spring 本身也提供了数据访问功能和 web 功能,以及可以很好的管理其他框架。

Spring体系结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mlZMdOL0-1647175543431)(C:\Users\褚哲希\AppData\Roaming\Typora\typora-user-images\1646736349497.png)]

Core Container(核心容器):

  • Beans: 管理 Beans

  • Core: Spring 核心

  • Context: 配置文件

  • ExpressionLanguage: SpEL 表达式

AOP(切面编程)

AOP 框架: Aspects

Data Access(数据库整合): JDBC, ORM, OXM, JMS, Transaction

Web(MVC Web 开发): Web, Servlet, Portlet, Struts

Test(Junit 整合)

官网地址:https://spring.io/

Spring Hello World 搭建

导入jar

开发类

编写配置文件(配置需要spring管理的类)

  • 容器实现类ClassPathXmlApplicationContext(“spring.xml”) 读取spring文件

    getBean(“对象名”)

pom.xml
<?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>com.ffyc</groupId>
    <artifactId>SpringPro</artifactId>
    <version>1.0</version>
    <name>SpringPro</name>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
        <junit.version>5.6.2</junit.version>
    </properties>

    <dependencies>
        <!-- spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.0</version>
            </plugin>
        </plugins>
    </build>
</project>
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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--
    配置spring要管理的对象,spring框架管理生成的对象我们成为一个bean
    id 对象名
    class 管理的类名
    -->
    <bean id="user" class="com.ffyc.spring.model.User"></bean>
</beans>
import com.ffyc.spring.model.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test1 {
    public static void main(String[] args) {
        /*
         启动spring框架,读取配置文件
         IOC 控制反转 是spring的核心功能
             控制反转 将生成对象的权利 反转给spring框架,由spring框架一同管理
        */
        ApplicationContext app = new ClassPathXmlApplicationContext("spring.xml"); //spring容器
        User user = app.getBean("user",User.class);
        System.out.println(user);
    }
}

IOC(控制反转)

​ 控制反转

​ 以前是正控,在哪用,在哪new

​ 现在是反控同一交给spring,交给spring管理的对象,spring在创建时,就可以为我们的对象添加额外的功能。

读作**“反转控制”(Inverse of Control)更好理解,不是什么技术,而是一种设计思想,就是**将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理。IOC 容器是具有依赖注入功能的容器,负责对象的实例化、对象的初始化,对 象和对象之间依赖关系配置、对象的销毁、对外提供对象的查找等操作,对象的整个生命周期都是由容器来控制。我们需要使用的对象都由 ioc 容器进行管理,不需要我们再去手动通过 new 的方式去创建对象,由 ioc 容器直接帮我们组装好,当我们需要使用的时候直接从 ioc 容器中直接获取就可以了。

正控:若要使用某个对象,需要自己去负责对象的创建

反控:若要使用某个对象,只需要从 Spring 容器中获取需要使用的对象,

不关心对象的创建过程,也就是把创建对象的控制权反转给了 Spring 框架.

**目的:**降低耦合度

底层实现方式: 解析 xml/扫描注解标签 + 工厂模式 + 反射机制

Spring Bean 管理

基于 xml 配置方式

bean 配置需要 spring 管理的类id 生成的对象名

class 全类名

name 对象别名,可以为多个

<?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要管理的对象,spring框架管理生成的对象我们成为一个bean
    id 对象名
    class 管理的类名
    name 定义对象名,定义多个
    -->
    <bean id="user" name="user1,user2" class="com.ffyc.spring.model.User"></bean>
</beans>
import com.ffyc.spring.model.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test1 {
    public static void main(String[] args) {
        /*
         启动spring框架,读取配置文件
         IOC 控制反转 是spring的核心功能
             控制反转 将生成对象的权利 反转给spring框架,由spring框架一同管理
        */
        ApplicationContext app = new ClassPathXmlApplicationContext("spring.xml"); 
        User user = app.getBean("user1",User.class);
//        User user = app.getBean("user1",User.class);
        System.out.println(user);
    }
}

scope:

  • singleton(默认值):在 Spring 中只存在一个 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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!--
        配置spring要管理的对象,spring框架管理生成的对象我们成为一个bean
        id 对象名
        class 管理的类名
        name 定义对象名,定义多个
        scope="singleton" 默认值 对象作用域
              singleton:单例的,只会创建一个对象 在spring框架启动时,就会创建对象
        -->
        <bean id="user" name="user1,user2" class="com.ffyc.spring.model.User" scope="singleton"></bean>
    </beans>
    
    public class Test1 {
        public static void main(String[] args) {
            ApplicationContext app = new ClassPathXmlApplicationContext("spring.xml");
            User user = app.getBean("user",User.class);
            System.out.println(user); //com.ffyc.spring.model.User@1794d431
            User user1 = app.getBean("user",User.class);
            System.out.println(user1); //com.ffyc.spring.model.User@1794d431
            //说明创建的是一个对象
        }
    }
    
  • prototype:原型 getBean()的时候都会 new 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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--
        配置spring要管理的对象,spring框架管理生成的对象我们成为一个bean
        id 对象名
        class 管理的类名
        name 定义对象名,定义多个
        scope="singleton" 默认值 对象作用域
              singleton:单例的,只会创建一个对象 在spring框架启动时,就会创建对象
        prototype:原型的 多例的 每次获取时,都会创建一个新的对象
        request:每次http请求创建一个
        session:每次会话创建一个
    -->
        <bean id="user" name="user1,user2" class="com.ffyc.spring.model.User" scope="prototype"></bean>
    </beans>
    
    package com.ffyc.spring.test;
    
    import com.ffyc.spring.model.User;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Test1 {
        public static void main(String[] args) {
            ApplicationContext app = new ClassPathXmlApplicationContext("spring.xml");
            User user = app.getBean("user",User.class);
            System.out.println(user); //com.ffyc.spring.model.User@604ed9f0
            User user1 = app.getBean("user",User.class);
            System.out.println(user1); //com.ffyc.spring.model.User@6a4f787b
            //创建两次对象
        }
    }
    
  • request:每次 http 请求都会创建一个 bean, 仅用于 WebApplicationContext环境

session:同一个 http session 共享一个 Bean, 不同 Session 使用不同的 Bean, 使用环境同上

Xml 配置方式依赖注入【DI:Dependency Injection】

指 Spring 创建对象的过程中,将对象依赖属性(简单值,集合,对象)通过配置设置给该对象。

实现 IOC 需要 DI 做支持

注入的方式:

  • set 方法注入

    <?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创建对象的同时,为对象中的属性赋值
          注入方式:
             set方法注入(常用)
             构造方法注入
        -->
        <bean id="user" name="user1,user2" class="com.ffyc.spring.model.User" scope="prototype">
            <!--set方法注入 无参构造方法-->
            <property name="num" value="100"></property>
            <property name="name" value="jim"></property>
        </bean>
    </beans>
    
    public class UserService {
        UserDao userDao; //注入
        public void save(){
           userDao.save();
        }
    }
    
    public class User {
        private int num;
        private String name;
    
        public User() {
            System.out.println("User无参构造方法");
        }
    
        public User(int num, String name) {
            System.out.println("User有参构造方法");
            this.num = num;
            this.name = name;
        }
    
        public int getNum() {
            return num;
        }
    
        public void setNum(int num) {
            this.num = num;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "num=" + num +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
    
  • 构造方法注入

    <?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创建对象的同时,为对象中的属性赋值
          注入方式:
             set方法注入(常用)
             构造方法注入
        -->
        <bean id="user" name="user1,user2" class="com.ffyc.spring.model.User" scope="prototype">
            <!--构造方法注入 调用有参的构造方法-->
            <constructor-arg name="num" value="101"></constructor-arg>
            <constructor-arg name="name" value="jim"></constructor-arg>
        </bean>
    </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/beans/spring-beans.xsd">
    <!--
      依赖注入:就是在spring创建对象的同时,为对象中的属性赋值
      注入方式:
         set方法注入(常用)
         构造方法注入
    -->
    <bean id="user" name="user1,user2" class="com.ffyc.spring.model.User" scope="prototype">
        <!--set方法注入-->
        <!--<property name="num" value="100"></property>
        <property name="name" value="jim"></property>-->
        <!--构造方法注入-->
        <constructor-arg name="num" value="101"></constructor-arg>
        <constructor-arg name="name" value="jim"></constructor-arg>
    </bean>
    <!--spring框架生成UserDao对象-->
    <bean id="userdao" class="com.ffyc.spring.dao.UserDao"></bean>

    <!--spring框架生成对象UserService,同时注入UserDao-->
    <bean id="userService" class="com.ffyc.spring.service.UserService">
        <!--ref="userdao"引用上面生成的对象-->
        <property name="userDao" ref="userdao"></property>
    </bean>
</beans>
package com.ffyc.spring.service;

import com.ffyc.spring.dao.UserDao;

public class UserService {
    //现在方式改变了,只需要定义即可,在创建UserService的同时,会将UserDao对象注入
    UserDao userDao; //注入

    public void save(){
        userDao.save();
    }

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}
package com.ffyc.spring.dao;

public class UserDao {
    public void save(){
        System.out.println("保存用户");
    }
}

注解方式实现

注解开发准备工作

注解需要的 jar 包注解功能封装在 AOP 包中,导入 Spring aop jar 包即可

开启注解扫描

<context:component-scan base-package="包名"> </context:component-scan>

注解创建对象

@Component(value=“user”)等于

@Service

@Repository

以上注解都可以实现创建对象功能,只是为了后续扩展功能,在不同的层使用不同的注解标记

@Scope(value=“prototype”) 原型

@Scope(value=“ singleton ”) 单例

注解方式注入属性【DI:Dependency Injection】

@Autowired

@Autowired 是 Spring 提供的注解,可以写在字段和 setter 方法上。如果写在字段上,那么就不需要再写 setter 方法。默认情况下它要求依赖对象必须存在,如果允许 null 值,可以设置它的 required 属性为 false。

byType 自动注入

该注解默认使用按类型自动装配 Bean 的方式。

byName 自动注入

如果我们想使用按照名称(byName)来装配,可以结合@Qualifier 注解一起使用。

需要在引用属性上联合使用注解@Autowired 与@Qualifier。@Qualifier 的value 属性用于指定要匹配的 Bean 的 id 值。

JDK 注解@Resource 自动注入

Spring 提供了对 jdk 中@Resource 注解的支持。@Resource 注解既可以按名称匹配 Bean,也可以按类型匹配 Bean。默认按照 ByName 自动注入

byName 注入引用类型属性

@Resource 注解指定其 name 属性,则 name 的值即为按照名称进行匹配的 Bean 的 id。

注解实现方式

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:context="http://www.springframework.org/schema/context"
       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/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--注解方式-->
    <!--开启spring的注解扫描功能,启动时,就会扫描所配置的包下面的类-->
    <context:component-scan base-package="com.ffyc.spring"> </context:component-scan>
</beans>
package com.ffyc.spring.model;

import org.springframework.stereotype.Component;

//@Component(value = "student")等同于<bean id="student" class="com.ffyc.spring.model.Student">
//等于配置spring扫描此类时,解析注解标签,功能与xml配置一样的
@Component(value = "student")
public class Student {
    private int num;
    private String name;

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
package com.ffyc.spring.dao;
import org.springframework.stereotype.Repository;
//@Repository(value="userDao")
@Repository
public class StudentDao {
    public void save(){
        System.out.println("保存学生");
    }
}
package com.ffyc.spring.service;

import com.ffyc.spring.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service(value = "studentService")
public class StudentService {
    /*
      @Autowired 自动注入,默认会根据类型查找
    */
    @Autowired
    StudentDao studentDao;

    public void save(){
        studentDao.save();
    }
}
package com.ffyc.spring.test;

import com.ffyc.spring.model.Student;
import com.ffyc.spring.service.StudentService;
import com.ffyc.spring.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test3 {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("spring.xml");
        StudentService studentService = app.getBean("studentService",StudentService.class);
        studentService.save();
    }
}

Spring JDBC

Spring 是个一站式框架:Spring 自身也提供了控制层的 SpringMVC 和 持久层的 Spring JdbcTemplate。

开发步骤

下载 Spring JdbcTemplate 的 jar 包:

<!-- spring-jdbc --> 
<dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-jdbc</artifactId> 
    <version>5.2.2.RELEASE</version> 
</dependency> 
<!-- 阿里数据源 --> 
<dependency> 
    <groupId>com.alibaba</groupId> 
    <artifactId>druid</artifactId> 
    <version>1.1.10</version> 
</dependency>

导入属性文件:

<context:property-placeholder location=“config.properties”/>

管理数据源对象 :

spring 管理与数据库链接 (数据源)

<bean id="dataSource"class="com.alibaba.druid.pool.DruidDataSource"> 
    <property name="driverClassName" value="${driverClassName}"></property> 
    <property name="url" value="${url}"></property>
    <property name="username" value="${uname}"></property> 
    <property name="password" value="${pwd}"></property> 
    <property name="initialSize" value="10"></property> 
    <property name="minIdle" value="5"></property> 
    <property name="maxActive" value="20"></property> 
</bean>

在配置文件中创建 JdbcTemplate :

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 
    <property name="dataSource" ref="dataSource"></property> 
</bean>

在类中获得 JdbcTemplate 对象,就可以直接使用。

JdbcTemplate 中常用的方法

execute:无返回值,可执行 ddl,增删改语句

update:执行新增、修改、删除语句;

queryForXXX:执行查询相关语句;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

//@Component(value = "student")等同于<bean id="student" class="com.ffyc.spring.model.Student">
//等于配置spring扫描此类时,解析注解标签,功能与xml配置一样的
@Component(value = "student")
@Scope(value = "prototype")
public class Student {
    private int num;
    private String name;

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
package com.ffyc.spring.dao;

import com.ffyc.spring.model.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

//@Repository 可直接通过类名调用
@Repository(value="studentDao")
public class StudentDao {
    @Autowired
    JdbcTemplate jdbcTemplate;

    public void save(){
        System.out.println("保存学生");
        //execute(String sql)用于执行ddl语句
        //jdbcTemplate.execute("create table test(id int,name varchar(20))");
        //jdbcTemplate.update("insert into student(num,name,gender)values(?,?,?)",200,"zhang","男");
        //jdbcTemplate.update("delete from student where id = ?", 26);

        List<Student> list = jdbcTemplate.query("select * from student where gender=?",
                new RowMapper<Student>() {
                    @Override
                    public Student mapRow(ResultSet resultSet, int i) throws SQLException {
                        Student student = new Student();
                        student.setNum(resultSet.getInt("num"));
                        student.setName(resultSet.getString("name"));
                        return student;
                    }
                }
                ,"男");
    }
}
package com.ffyc.spring.service;

import com.ffyc.spring.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service(value = "studentService")
public class StudentService {
    /*
      @Autowired 自动注入,默认会根据类型查找
      @Autowired 此注解标签时spring框架提供的注解标签,可以根据属性的类型(默认) 或 对象的名字查找
      默认情况注入时,值不能为空

    */
    @Autowired
//    @Resource(name = "studentDao")
    StudentDao studentDao;

    public void save(){
        studentDao.save();
    }
}
package com.ffyc.spring.test;

import com.ffyc.spring.model.Student;
import com.ffyc.spring.service.StudentService;
import com.ffyc.spring.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test3 {
    public static void main(String[] args) {

        ApplicationContext app = new ClassPathXmlApplicationContext("spring.xml");
        /*Student student = app.getBean("student",Student.class);
        System.out.println(student);*/
        StudentService studentService = app.getBean("studentService",StudentService.class);
        studentService.save();
    }
}
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:context="http://www.springframework.org/schema/context"
       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/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--注解方式-->
    <!--开启spring的注解扫描功能,启动时,就会扫描所配置的包下面的类-->
    <context:component-scan base-package="com.ffyc.spring"> </context:component-scan>

    <!--导入属性文件-->
    <context:property-placeholder location="config.properties"></context:property-placeholder>

    <!--配置阿里巴巴数据源管理的类,交给spring统一管理-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${url}"></property>
        <property name="driverClassName" value="${driverClassName}"></property>
        <property name="username" value="${uname}"></property>
        <property name="password" value="${password}"></property>
        <property name="initialSize" value="5"></property>
        <property name="maxActive" value="20"></property>
        <property name="maxWait" value="100"></property>
    </bean>

    <!--配置spring中对JDBC进行的封装的JDBCTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

</beans>

不使用 AOP 的开发方式

先定义好接口与一个实现类,该实现类中除了要实现接口中的方法外,还要再写两个非业务方法。非业务方法也称为交叉业务逻辑:

➢ doTransaction():用于事务处理

➢ doLog():用于日志处理

然后,再使接口方法调用它们。接口方法也称为主业务逻辑。

AOP

AOP 概述

AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。

AOP 是 OOP 的延续,是软件开发中的一个热点,也是 Spring 框架中的一个重要内容。利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

AOP、OOP 在字面上虽然非常类似,但却是面向不同领域的两种设计思想。OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。而 AOP 则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的 某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设计思想在目标上有着本质的差异。

面向切面编程的好处就是: 减少重复,专注业务;

注意:面向切面编程只是面向对象编程的一种补充。

核心原理:

使用动态代理的方式在执行方法前后或者出现异常的时候做加入相关的逻辑.

使用案例:

事务处理:开启事务,关闭事务,出现异常后回滚事务

权限判断:在执行方法前,判断是否具有权限

日志:在执行前进行日志处理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x8Y60FHB-1647175543435)(E:\学习笔记\JavaEE\图\AOP使用案例.png)]

AOP 的基本概念

**连接点(Joinpoint):**类中可以被增强的方法,这个方法就被称为连接点 。

**切入点(pointcut):**类中有很多方法可以被增强,但实际中只有 add 和 update被增了,那么 add 和 update方法就被称为切入点(实际实现的连接点)。

通知(Advice): 通知是指一个切面在特定的连接点要做的事情(增强的功能)。通知分为方法执行前通知,方法执行后通知,环绕通知等。

**切面(Aspect)😗*把通知添加到切入点的过程叫切面。

目标(Target): 代理的目标对象(要增强的类) 。

代理(Proxy): 向目标对象应用通知之后创建的代理对象。

springAOP 实现

对于 AOP 这种编程思想,很多框架都进行了实现。Spring 就是其中之一,可以完成面向切面编程。

然而,AspectJ 也实现了 AOP 的功能,AspectJ 是一个基于 Java 语言的 AOP框架,它提供了强大的 AOP 功能,且其实现方式更为简捷,使用更为方便, 而 且还支持注解式开发。所以,Spring 又将 AspectJ 的对于 AOP 的实现也引 入到了自己的框 架中。

在 Spring 中使用 AOP 开发时,一般使用 AspectJ 的实现方式。 AspectJ 是一个优秀面向切面的框架,它扩展了 Java 语言,提供了强大的切面实现。

AspectJ 中常用的通知有五种类型:

  • 前置通知
  • 后置通知
  • 环绕通知
  • 异常通知
  • 最终通知

下载 AOP 相关 jar

<dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-aspects</artifactId> 
    <version>5.2.2.RELEASE</version> 
</dependency>

基于 aspectj 的 xml 配置方式实现

<bean id="aopdemo" class="com.ff.spring.aop.AopDemo"></bean> 
<aop:config> 
    <!-- 配置切入点 --> 
    <aop:pointcut expression="execution(* com.ff.spring.service.UserService.adduser(..))" id="adduser"/> 
    <aop:pointcut expression="execution(* com.ff.spring.service.UserService.*(..))" id="allmethod"/> 
    <!-- 配置通知和切入点 --> 
    <aop:aspect ref="aopdemo"> 
        <aop:before method="savelog" pointcut-ref="adduser"/> 
        <aop:after method="savelog" pointcut-ref="adduser"/> 
        <aop:around method="aroundAdvice" pointcut-ref="adduser"/> 
        <aop:after-throwing method="exceptionAdvice" pointcut-ref="allmethod" throwing="e" /> 
    </aop:aspect> 
</aop:config>

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

    <!--注解方式-->
    <!--开启spring的注解扫描功能,启动时,就会扫描所配置的包下面的类-->
    <context:component-scan base-package="com.ffyc.spring"> </context:component-scan>
    <!--导入另一个配置文件-->
    <import resource="db.xml"></import>
</beans>
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--注解方式-->
    <!--开启spring的注解扫描功能,启动时,就会扫描所配置的包下面的类-->
    <context:component-scan base-package="com.ffyc.spring"> </context:component-scan>

    <!--导入属性文件-->
    <context:property-placeholder location="config.properties"></context:property-placeholder>

    <!--配置阿里巴巴数据源管理的类,交给spring统一管理-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${url}"></property>
        <property name="driverClassName" value="${driverClassName}"></property>
        <property name="username" value="${uname}"></property>
        <property name="password" value="${password}"></property>
        <property name="initialSize" value="5"></property>
        <property name="maxActive" value="20"></property>
        <property name="maxWait" value="100"></property>
    </bean>

    <!--配置spring中对JDBC进行的封装的JDBCTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--基于xml方式实现aop配置-->
    <!--配置装有通知的类,将此类交给spring管理-->
    <bean id="myutil" class="com.ffyc.spring.util.MyUtil" ></bean>
    <!--编织/编入-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="save" expression="execution(* com.ffyc.spring.service.StudentService.save(..))"/>
        <aop:pointcut id="delete" expression="execution(* com.ffyc.spring.service.StudentService.delete(..))"/>
        <!--为切入点配置通知-->
        <aop:aspect ref="myutil">
            <!--前置通知-->
            <aop:before method="saveLog" pointcut-ref="save"></aop:before>
            <!--后置通知-->
            <aop:after method="commit" pointcut-ref="save"></aop:after>
            <!--环绕通知-->
            <aop:around method="around" pointcut-ref="delete"></aop:around>
            <!--异常通知-->
            <aop:after-throwing method="exception" throwing="e" pointcut-ref="save"></aop:after-throwing>
        </aop:aspect>
    </aop:config>
</beans>
package com.ffyc.spring.util;

import org.aspectj.lang.ProceedingJoinPoint;

public class MyUtil {
    /*通知*/
    public void commit(){
        System.out.println("关闭连接,提交事务");
    }

    /*通知*/
    public void saveLog(){
        System.out.println("保存日志");
    }

    /*环绕通知*/
    public void around(ProceedingJoinPoint point){
        System.out.println("保存日志功能");
        try {
            point.proceed(); //调用我们自己的业务代码
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("关闭连接,提价事务功能");
    }

    /*异常通知*/
    public void exception(Throwable e){
        System.out.println("出异常了:"+e.getMessage());
    }
}
package com.ffyc.spring.service;

import com.ffyc.spring.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service(value = "studentService")
public class StudentService {
    /*
      @Autowired 自动注入,默认会根据类型查找
      @Autowired 此注解标签时spring框架提供的注解标签,可以根据属性的类型(默认) 或 对象的名字查找
      默认情况注入时,值不能为空

    */
//    @Autowired
//    @Resource(name = "studentDao")
    @Resource //通过类型查找注入
    StudentDao studentDao;

    public void save(){
//        studentDao.save();
        System.out.println("保存");
        System.out.println(10/0); //异常通知用
    }

    public void delete(){
        System.out.println("删除");
    }
}
package com.ffyc.spring.test;

import com.ffyc.spring.service.StudentService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test1 {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("spring.xml");
        StudentService studentService = app.getBean("studentService",StudentService.class);
        studentService.save();
        studentService.delete();
    }
}

注解方式

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

    <!--注解方式-->
    <!--开启spring的注解扫描功能,启动时,就会扫描所配置的包下面的类-->
    <context:component-scan base-package="com.ffyc.spring"> </context:component-scan>
    <!--导入另一个配置文件-->
    <import resource="db.xml"></import>

    <!--基于注解方式实现aop 开启自动配置-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
package com.ffyc.spring.util;

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

@Component
@Aspect
public class MyUtil {
    /*通知*/
    //save(String) 仅能调用String类型
    @After("execution(* com.ffyc.spring.service.StudentService.save(..))")
    public void commit(){
        System.out.println("关闭连接,提交事务");
    }

    /*通知*/
    //save(..) ..表示可以调用任何类型
    @Before("execution(* com.ffyc.spring.service.StudentService.save(..))")
    public void saveLog(){
        System.out.println("保存日志");
    }

    /*环绕通知*/
    @Around("execution(* com.ffyc.spring.service.StudentService.delete(..))")
    public void around(ProceedingJoinPoint point){
        System.out.println("保存日志功能");
        try {
            point.proceed(); //调用我们自己的业务代码
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("关闭连接,提价事务功能");
    }

    /*异常通知*/
    @AfterThrowing(value = "execution(* com.ffyc.spring.service.StudentService.delete(..))",throwing = "e")
    public void exception(Throwable e){
        System.out.println("出异常了:"+e.getMessage());
    }
}
package com.ffyc.spring.test;

import com.ffyc.spring.service.StudentService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test1 {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("spring.xml");
        StudentService studentService = app.getBean("studentService",StudentService.class);
        studentService.save();
        studentService.delete();
    }
}

Spring 事物管理

事物可以看做是由对数据库若干操作组成的一个单元。

我们在开发企业应用时,对于业务人员的一个操作实际是对数据读写的多步操作的结合。由于数据操作在顺序执行的过程中,任何一步操作都有可能发生异常,异常会导致后续操作无法完成,此时由于业务逻辑并未正确的完成,之前成功操 作数据的并不可靠,需要在这种情况下进行回退。

事务的作用就是为了保证用户的每一个操作都是可靠的,事务中的每一步操作都必须成功执行,只要有发生异常就回退到事务开始未进行操作的状态,这些操作要么都完成,要么都取消,从而保证数据满足一致性的要求Spring 中的事务管理分为两种形式,一种是编程式事务,一种是声明式事务。

编程式事务

在 项 目 中 很 少 使 用 , 这 种 方 式 需 要 注 入 一 个 事 务 管 理 对 象 TransactionTemplate ,然后在我们代码中需要提交事务或回滚事务时自己写代码实现。

需要在业务代码中,显示的提交事务 ,使用TransactionTemplate transactionTemplate;
transactionTemplate.execute() 在此方法中执行业务代码

声明式事务

声明式事物就是使用注解标签对需要添加事务的方法进行声明即可,这样次方法就会在事务管理中执行

管理建立在 AOP 基础上,本质是对方法前后进行拦截,所以声明式事务是方法级别的。

Spring 声明式事物管理方式有两种:

  • 基于 xml 配置

  • 基于注解实现

Spring 事物管理 APIPlatformTransactionManager 事物管理器接口

Spring 针对不同的 dao 框架,提供了不同的实现类,Jdbc,mybatis 事物管理实现类是 DataSourceTransactionManager.

配置事物管理器
<!-- 配置 spring 事务管理类, 并注入数据源 --> 
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="dataSource"></property> 
</bean>
注解方式
<!-- 开启注解事务管理 --> 
<tx:annotation-driven transaction-manager="transactionManager"/>

在 service 中控制事务

@Service(value=“userservice”)

@Transactional(propagation=Propagation.REQUIRED)

声明式事务不生效的场景
  • 调用同一个类中被@Transactional 修饰的方法

  • 注解@Transactional 所在类非spring容器管理的bean 自己new的,没有添加注解标签@Service

  • 异常被 catch 捕获导致@Transactional 失效

  • 数据库引擎不支持事务 mysql有好几种存储引擎,mysql中只有innoDB支持事物

  • @Transactional 注解属性 propagation 设置错误

spring中是如何事物管理的

声明式事务

编程式事物

事务管理实现原理: aop面向切面,不用在再业务代码中显示的提交,就可以实现事务的增强功能

aop实现的原理:动态代理

动态代理有哪几种:jdk代理、cglib代理

spring中的事物传播行为

事务传播行为

传播,也就是至少两个方法之间在相互调用。

事务是数据库的行为,事务传播行为是spring框架自己添加的功能

即然是传播,那么至少有两个东西,才可以发生传播。单体不存在传播这个行为。

事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。事务传播行为是 Spring 框架独有的事务增强特性,他不属于的事务实际提供方数据库行为.

spring中提供了七种传播行为

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
public class LogDao {
    @Autowired
    JdbcTemplate jdbcTemplate;

    @Transactional
    public void addlog(){
        jdbcTemplate.update("intsert into log(content)values ('添加账号')");
    }
}
public class Test2 {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("spring.xml");
        BankService bankService = app.getBean("bankService",BankService.class);
        bankService.addAccount();
    }
}

1.PROPAGATION_REQUIRED

默认的,如果有事务就加入到当前事务中执行

指定的方法必须在事务内执行,若当前存在事务,加入到当前事务中,若当前没有事务,则创建一个新事务,这种传播行为是最常见的,也是 spring 默认的传播行为。

有事务
import com.ffyc.spring.dao.BankDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.swing.plaf.PanelUI;

@Service(value = "bankService")
//@Transactional添加在类的上面,表示此类中所有方法,都在spring事务管理中进行
public class BankService {

    @Autowired
    BankDao bankDao;
    @Autowired
    LogService logService;

    @Transactional(propagation = Propagation.REQUIRED)
    public  void zhuanzhang(){
        bankDao.jian();
        bankDao.jia();
    }

    /*
          Propagation.REQUIRED  会开启事务,在事务中执行的
          A方法 是有事务的,事务传播行为是REQUIRED(是必须的)
          A方法没有事务
    */
    @Transactional(propagation = Propagation.REQUIRED) //默认枚举类型
    public void addAccount(){
        logService.addLog();
        System.out.println(10/0);
        bankDao.addAccount();
    }


}

package com.ffyc.spring.service;

import com.ffyc.spring.dao.LogDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class LogService {
    @Autowired
    LogDao logDao;
    /*
    Propagation.REQUIRED  会开启事务,在事务中执行的 REQUIRED(必须的)
    A方法 是有事务的,事务传播行为是REQUIRED
       B方法的传播行为也是REQUIRED,那么B方法就会加入到A方法的事务中执行,两个合二为一
       A方法中出现了异常,B方法事务也是不会提交的
    */
    @Transactional(propagation = Propagation.REQUIRED)
    public void addLog(){
        logDao.addlog(); //事务默认提交
    }
}
无事务
@Service(value = "bankService")
//@Transactional添加在类的上面,表示此类中所有方法,都在spring事务管理中进行
public class BankService {

    @Autowired
    BankDao bankDao;
    @Autowired
    LogService logService;

    @Transactional(propagation = Propagation.REQUIRED)
    public  void zhuanzhang(){
        bankDao.jian();
        bankDao.jia();
    }

    /*
          Propagation.REQUIRED  会开启事务,在事务中执行的
          A方法 是有事务的,事务传播行为是REQUIRED(是必须的)
          A方法 没有事务
    */
    //@Transactional(propagation = Propagation.REQUIRED) //默认枚举类型
    public void addAccount(){
        logService.addLog();
//        System.out.println(10/0);
        bankDao.addAccount();
    }
}
@Service
public class LogService {
    @Autowired
    LogDao logDao;
    /*
    Propagation.REQUIRED  会开启事务,在事务中执行的 REQUIRED(必须的)
    A方法没有事务
       那么B方法就自己开启事务,独立的执行   
    */
    @Transactional(propagation = Propagation.REQUIRED)
    public void addLog(){
        logDao.addlog(); //事务默认提交
    }
}

2.PROPAGATION_SUPPORTS

如果有事务就加入到当前事务中执行,如果没有事务也就没有事务

支持当前事务,如果当前没有事务,就以非事务方式执行。

有事务
@Service(value = "bankService")
public class BankService {

    @Autowired
    BankDao bankDao;
    @Autowired
    LogService logService;

    @Transactional(propagation = Propagation.REQUIRED)
    public  void zhuanzhang(){
        bankDao.jian();
        bankDao.jia();
    }

    @Transactional(propagation = Propagation.REQUIRED) //默认枚举类型
    public void addAccount(){
        logService.addLog(); 
        bankDao.addAccount();
    }
}
@Service
public class LogService {
    @Autowired
    LogDao logDao;

    /*
      A方法有事务  Propagation.REQUIRED
        B方法 传播行为是Propagation.SUPPORTS
        那么B方法就加入到A方法事务中进行
    */
    @Transactional(propagation = Propagation.SUPPORTS)
    public void addLog(){
        logDao.addlog(); //事务默认提交
        System.out.println(10/0);
    }
}
无事务
@Service(value = "bankService")
public class BankService {

    @Autowired
    BankDao bankDao;
    @Autowired
    LogService logService;

    @Transactional(propagation = Propagation.REQUIRED)
    public  void zhuanzhang(){
        bankDao.jian();
        bankDao.jia();
    }

    //@Transactional(propagation = Propagation.REQUIRED) //默认枚举类型
    public void addAccount(){
        logService.addLog(); 
        bankDao.addAccount();
    }
}
@Service
public class LogService {
    @Autowired
    LogDao logDao;
    /*
      A方法有事务  Propagation.REQUIRED
        B方法 传播行为是Propagation.SUPPORTS
        那么B方法就加入到A方法事务中进行
      A方法如果没有事务
        那么B方法也就在无事务中进行
    */
    @Transactional(propagation = Propagation.SUPPORTS)
    public void addLog(){
        logDao.addlog(); //事务默认提交
        System.out.println(10/0);
    }
}

3.PROPAGATION_REQUIRES_NEW

如果有事务就会挂起当前事务,自己新开启一个独立的事务运行,如果没有事务也会开启一个独立的事务运行。

总是新建一个事务,如果当前存在事务,把当前事务挂起,直到新建的事务结束。

4.PROPAGATION_NOT_SUPPORTED

不支持事务,即使有事务,也会挂起

5.PROPAGATION_NEVER

Spring 集成 Mybatis

spring框架就像是一个管家,凭借着IOC功能(IOC创建管理对象),可以非常轻松来集成其他框架。

搭建SSM框架

早期SSM指的是spring(管理) struts2(web层 servlet) mybatis(jdbc dao层),再之前还有一个SSH指的是spring struts2 hibernate

现在的SSM指的是spring、springMVC(spring体系中的一部分)、mybatis

导入 mybatis jar 包

Spring 结合 mybatis 插件包

<dependency> 
    <groupId>org.mybatis</groupId> 
    <artifactId>mybatis-spring</artifactId>
    <version>1.3.1</version> 
</dependency>

配置 sqlSessionFactory

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource"></property> 
    <property name="configLocation" value="mybatis-config.xml"></property> 
    <property name="mapperLocations" value="com/ff/*Mapper.xml"> </property> 
</bean>

指定生成接口代理

<bean id="mapperFactory" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 
    <property name="basePackage" value="com.ff.ssm.dao"></property> 
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"> </property> </bean>

步骤

1.导入框架所需要的jar包

pom.xml 
<?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>com.ffyc</groupId>
    <artifactId>ssm</artifactId>
    <version>1.0</version>
    <name>ssm</name>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
        <junit.version>5.6.2</junit.version>
    </properties>

    <dependencies>
        <!--spring集成mybatis使用的jar-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>

        <!-- spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>

        <!-- spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>

        <!--spring-aop-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>

        <!--springMVC-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>

        <!-- 阿里数据源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>
        
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.2</version>
        </dependency>

        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.0</version>
            </plugin>
        </plugins>
    </build>
</project>

2.创建类

public class User {
    private Integer id;
    private String account;
    private String password;


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", account='" + account + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}
@Service(value = "loginService")
@Transactional
public class LoginService {

     @Autowired
     LoginDao loginDao;

     /*
        获得sqlsession,创建代理对象
        关闭sqlsession,提交事务
        通通都被spring管理了
      */
     public User login(User user){
         return loginDao.login(user);
     }
}
@Repository
public interface LoginDao {
      User login(User user);
}

3.创建mybatis的配置文件

删除多余的数据库连接,导入sql映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--sql映射文件  namespace名字必须与接口的类路径一致-->
<mapper namespace="com.ffyc.ssm.dao.LoginDao">


    <select id="login" parameterType="User" resultType="User">
         select  id,account from user where account=#{account} and password=#{password}
    </select>

</mapper>
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:context="http://www.springframework.org/schema/context"
       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/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

       <!--开启spring的注解扫描功能, 启动时,就会扫描所配置的包下面的类-->
       <context:component-scan base-package="com.ffyc.ssm"> </context:component-scan>
       <!--导入另一个配置文件-->
       <import resource="spring_mybatis.xml"></import>

       <!--基于注解方式实现aop  开启自动配置-->
       <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
mybatis.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>
  <!--mybatis核心配置文件-->
    <!--全局设置-->
    <settings>
        <!--日志组件配置-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!--从数据库命名user_gender  自动映射到java userGender-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--开启mybatis二级缓存-->
        <setting name="cacheEnabled" value="true"/>
    </settings>

    <!--配置类型别名-->
    <typeAliases>
        <typeAlias type="com.ffyc.ssm.model.User" alias="User"></typeAlias>
    </typeAliases>
</configuration>
db.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:context="http://www.springframework.org/schema/context"
       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/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

       <!--导入属性文件-->
      <context:property-placeholder location="classpath:config.properties"></context:property-placeholder>

       <!--配置阿里巴巴数据源管理的类,交给spring统一管理-->
       <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
           <property name="url" value="${url}"></property>
           <property name="driverClassName" value="${driverClassName}"></property>
           <property name="username" value="${uname}"></property>
           <property name="password" value="${password}"></property>
           <property name="initialSize" value="5"></property>
           <property name="maxActive" value="20"></property>
           <property name="maxWait" value="100"></property>
       </bean>

    <!-- 配置 spring 事务管理类, 并注入数据源 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 开启注解事务管理 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

4.spring中配置mybatis

spring_mybatis.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:context="http://www.springframework.org/schema/context"
       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/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

    <import resource="db.xml"></import>

      <!--spring管理生成sqlSessionFactory对象-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
          <property name="dataSource" ref="dataSource"></property><!--注入数据源-->
          <!--导入mybatis核心配置文件-->
          <property name="configLocation" value="classpath:mybatis.xml"></property>
          <!--模糊匹配sql映射文件-->
          <property name="mapperLocations" value="classpath:mapper/*Mapper.xml">
        </property>
    </bean>

    <!--为指定包中的接口生成代理对象-->
    <bean id="mapperFactory" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.ffyc.ssm.dao"></property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    </bean>

</beans>

5.测试ssm

public class Test {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("spring.xml");
        LoginService loginService = app.getBean("loginService",LoginService.class);
        User user = new User();
             user.setAccount("admin");
             user.setPassword("1111");
           User u = loginService.login(user);
        System.out.println(u);
    }
}

.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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd”>

<import resource="db.xml"></import>

  <!--spring管理生成sqlSessionFactory对象-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
      <property name="dataSource" ref="dataSource"></property><!--注入数据源-->
      <!--导入mybatis核心配置文件-->
      <property name="configLocation" value="classpath:mybatis.xml"></property>
      <!--模糊匹配sql映射文件-->
      <property name="mapperLocations" value="classpath:mapper/*Mapper.xml">
    </property>
</bean>

<!--为指定包中的接口生成代理对象-->
<bean id="mapperFactory" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.ffyc.ssm.dao"></property>
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
```

5.测试ssm

public class Test {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("spring.xml");
        LoginService loginService = app.getBean("loginService",LoginService.class);
        User user = new User();
             user.setAccount("admin");
             user.setPassword("1111");
           User u = loginService.login(user);
        System.out.println(u);
    }
}
举报

相关推荐

第七章

第七章:事务

第七章:集合

第七章 类

第七章 数组

第七章 集合

第七章总结

第七章 测试

0 条评论