笑着学spring - (2) - SpringJDBC 与 AOP介绍

前言

 ladies and gentleman 你们好 ,我是羡羡 , 这节我们来介绍 Spring JDBC 与 AOP

 

记得笑着学奥😊

目录

🙏Spring JDBC

🎃AOP(面向切面)

💍连接点: 

💼通知

🧢结语 : 


Spring JDBC

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

🙏首先我们需要在maven导入Spring JDBC的 jar 依赖
<!-- spring-jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.2.RELEASE</version>
</dependency>

但是spring并不直接参与数据库的连接 , 我们可以使用一些第三方的数据库组件

   这里我们使用阿里的druid 数据源,导入jar

阿里 druid(德鲁伊)  数据库连接组件  自身还提供了数据库连接池技术  sql监控

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

druid 具有以下功能

数据库连接  封装了jdbc
    数据库连接池   频繁的连接数据库 创建销毁连接对象  Connection  SqlSession  开销较大
            🎃 创建一个连接对象的池子   与数据库交互时,可以先从连接池中获取连接,用完后不进行销毁,只是还回到连接池
             减少创建销毁的开销
        
      让Spring管理创建Druid数据库连接对象

连接我们使用的是mysql数据库 , 所以jar 也是必不可少

创建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"

       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">
    <!--读入文件-->
    <context:property-placeholder location="config.properties"/>

    <!--配置数据源-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${driverName}"/>
        <property name="url" value="${urlName}"/>
        <property name="username" value="${uName}"/>
        <property name="password" value="${pwd}"/>
        <!--initialSize为初始化连接个数-->
        <property name="initialSize" value="${initialSize}"/>
        <!--maxActive为最大连接数-->
        <property name="maxActive" value="${maxActive}"/>
    </bean>

    <!--spring提供JdbcTemplate封装类-->
    <!--启动spring时创建jdbcTemplate类-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="druidDataSource"/>
    </bean>
</beans>
driverName=com.mysql.cj.jdbc.Driver
urlName=jdbc:mysql://127.0.0.1:3306/mybatis_db?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
uName=root
pwd=root
initialSize=5
maxActive=10

💍在 spring.xml 导入 db.xml 文件 

 <import resource="db.xml"/>
@Repository(value = "userDao")
public class UserDao {
    //注入JdbcTemplate
    @Autowired
    JdbcTemplate jdbcTemplate;
    public void saveUser(){
        jdbcTemplate.update("insert into admin(account,password,sex) values (?,?,?)","li","111","男");
    }
}
ApplicationContext app = new ClassPathXmlApplicationContext("spring.xml");

UserService userService=app.getBean("userService",UserService.class);

userService.save();   //调用执行

     
      💼 JdbcTemplate里面提供的方法也可以支持我们对数据库的各种操作(查询等),在数据库连接方面 ,我们后面都会使用mybatis框架 , 所以JdbcTemplate就不再讲述过多

      但是后面我们需要引入spring事务管理, 所以这里JdbcTemplate还是得了解


AOP(面向切面)

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

这么说不好理解 , 我们先来看如果不使用AOP的方式写代码是怎样去写的
 
🎃这里为了示例, 请出我的好兄弟 : 李雷(虽然我不知道他是否愿意, 我猜他知道的话肯定是下面这个表情,hhhhhhhhh)

        例如 : 李雷你一会下去吃饭把垃圾倒了, 或者不吃饭出去玩之前把垃圾倒了
 
那么从编程的思想来看, 这里有三个方法 :  吃饭 , 倒垃圾 , 出去玩
这里我们看出 , 无论李雷是吃饭还是出去玩 , 那么他都应该倒垃圾

所以我们直接可以将倒垃圾这个功能提取出来, 把倒垃圾这个功能看成一个横切面

让功能切入到我们的业务代码中即可

不使用AOP是这样来做的 : 

public void method1(){
        System.out.println("李雷吃饭");
        method3();
    }

    public void method2(){
        System.out.println("李雷出去玩");
        method3();
    }

    public void method3(){
        System.out.println("倒垃圾");
    }

 我们把倒垃圾抽取出去, 在 method1() 与 method2() 去调用这个方法

但为什么可以纯java实现 , 我们还要去使用AOP呢 ? 
 

      因为在平时的开发过程中 , 代码量比较大, 采用这样一直调用的方式 , method3直接侵入到其他的业务代码中, 这样很容易出现问题. 使用AOP的方式  , 它采用动态代理的方式来为我们的业务代码添加相应的逻辑 , 不需要我们去考虑这么多, 降低了耦合度,减少重复,专注业务


     我们现在来正式介绍AOP的使用方式(这里采用注解方式)
       
       对于AOP的实现,我们这里使用 AspectJ 这样一个框架, Spring对其进行了管理,AspectJ 是一个优秀面向切面的框架,它扩展了 Java 语言,提供了强大的切面实现。
<dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-aspects</artifactId> 
    <version>5.2.2.RELEASE</version> 
</dependency>

在maven导入AOP所需 jar

<aop:aspectj-autoproxy/>

在Spring.xml中 开启AspectJ 支持

连接点: 


这里需要介绍几个专业词 : 

💍 连接点(Joinpoint):类中可以被增强的方法,这个方法就被称为连接点
       
      无论李雷是否是吃饭还是出去玩, 我们都可以让它倒垃圾 , 那么此时吃饭和出去玩这两个方法就是连接点
 
💍 切入点(pointcut):类中有很多方法可以被增强,但实际中只有 add 和 update 被增了,那么 add 和 update 方法就被称为切入点(实际实现的连接点)

     李雷这时候选择了去吃饭, 那么此时去吃饭这个方法就是切入点
 
💍 通知(Advice): 通知是指一个切面在特定的连接点要做的事情(增强的功能)。通知分为方法执行前通知,方法执行后通知,环绕通知等
   
      这里通知指的就是倒垃圾这件事, 我们让李雷吃饭前倒垃圾, 就是前置通知, 饭吃完倒垃圾就是后置通知
 
💍 切面(Aspect):把通知添加到切入点的过程叫切面

    切面就是我们告诉李雷去吃饭的话记得倒垃圾这个过程
 
💍 目标(Target): 代理的目标对象(要增强的类)

    目标是我们具体去增强方法所属的类(目标类)
 
💍 代理(Proxy): 向目标对象应用通知之后创建的代理对象

   我们仅仅配置了AOP ,那么方法执行时, 谁去执行切面(增强的功能)呢? 答案就是代理对象帮我们去调用的
 
注解实现AOP如下 : 
 
配置切面类 : 
 
@Component
@Aspect
public class AopDemo {

    @Before("execution(* com.ff.spring.dao.UserDao.methodEat(..))")
    public void method(){
        System.out.println("倒垃圾");
    }
}

@Component 这个注解标签是将这个类交给Spring管理
@Aspect 说明这个类里的方法将被配置为切面
@Before() 代表前置通知

@Repository(value = "userDao")
public class UserDao {
    //将被增强的方法
    public void methodEat(){
        System.out.println("李雷去吃饭");
    }
}
这里我们看到标签中有这样一个表达式
 
execution(* com.ff.spring.dao.UserDao.methodEat(..))
      🎃 可以看出 , 它配置的是我们要增强的方法(此处为methodEat()) , 前面 * 表示这个方法返回值 , method(..) 中 .. 表示这个方法里可能有多个参数 ,例如我们上面这个方法 返回值void,没有参数, 所以这里也可以将 * 换成 void , .. 可以直接去掉
ApplicationContext app = new ClassPathXmlApplicationContext("spring.xml");
UserDao userDao=app.getBean("userDao",UserDao.class);
userDao.methodEat();

测试 : 

可以看到, 前置通知生效 
🎃这里我们载介绍一下后置通知, 异常通知, 环绕通知, 最终通知

@After ( "execution(* com.ff.spring.demo1.dao.UserDao.*(..))" )    后置通知注解

通知

 异常通知

@AfterThrowing(value = "execution(* com.ff.spring.demo1.dao.UserDao.*(..))",
        throwing = "e") 
public void afterthrow(Throwable){ 
    System.out.println("afterthrow"); 
}
这里有个参数 throwing , "e" 就代表返回的异常对象,我们可以通过异常对象获得异常的信息
 
🎃异常通知就是出了异常的话才会通知 , 例如李雷还没倒垃圾 ,然后被辅导员碰巧查宿(出现了异常) , 这时候就得指定异常通知去做什么事情
 
最终通知
@AfterReturning("execution(* com.ff.spring.demo1.dao.UserDao.*(..))") 
public void afterreturn(){ 
    System.out.println("afterreturn"); 
}

最终通知是在方法return后执行的通知
环绕通知

@Around("execution(* com.ff.spring.dao.UserDao.methodEat1(..))")
    public void around(ProceedingJoinPoint point){
        System.out.println("倒垃圾");
        try {
            point.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            System.out.println("快倒垃圾");
        }
        System.out.println("倒垃圾");
    }

       通过代码就可以看出 , 环绕通知其实可以代替以上通知 , 你可以在环绕通知中单独使用前置,后置,或者异常通知 , 环绕通知也是一个综合通知
结果 : 

这里相当于我们在环绕通知中使用了前置和后置 , 但是这里没有出现异常,所以异常通知不会执行
 

结语 : 

      这节我们介绍了SpringJDBC 与 AOP , 后面我们将会引入Spring事务管理这样一个模块, 所以这

两个要先介绍 ,最后感谢阅读😊

     学spring一定要笑, 哎 ,笑着学, 嘿嘿

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值