spring学习笔记

本文详细介绍了Spring框架,包括其作为Java EE轻量级框架的优势、缺点、发展历程以及核心特性如IOC/DI和AOP。Spring通过控制反转和依赖注入降低了耦合度,提供了面向切面编程的能力,并支持声明式事务管理。此外,文章还涵盖了Spring的单元测试、配置文件拆分以及JDBCTemplate的使用方法,是学习和理解Spring框架的全面指南。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

spring学习笔记

框架: 一个java应用程序的半成品项目,该项目中对java的软件开发进行了一部分的封装和定义标准,我们使用时 只需要学习框架,则会学会使用该框架开发新项目,再开发中使用框架可以提高开发效率,有利于团队开发。

​ 缺点:

​ 1,需要导入大量的jar包,会出现版本冲突

​ 2,项目运行效率低

​ 优点:

​ 1,提高开发效率

​ 2,利于团队开发

​ 3,有利于后期的维护

springBoot mybatis —> SM

springmvc spring mybatis —> SSM

struts2 spring hibernate —> SSH

目标:

​ spring简介

​ spring核心

​ IOC/DI

​ AOP

​ 声明式事务管理

​ jdbctemplete

spring简介

Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control: 反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层 Spring MVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多 著名的第三方框架和类库,逐渐成为使用最多的 Java EE 企业应用开源框架。

轻量级框架, Java EE的春天,当前最主流框架。

IOC/DI 反转控制 依赖注入

AOP 面向切面编程

Spring的发展历史:

​ 1997 年 IBM 提出了 EJB 的思想

​ 1998 年,SUN 制定开发标准规范 EJB1.0

​ 1999 年,EJB1.1 发布

​ 2001 年,EJB2.0 发布

​ 2003 年,EJB2.1 发布

​ 2006 年,EJB3.0 发布

Rod Johnson(spring 之父)

​ Expert One-to-One J2EE Design and Development(2002)

​ 阐述了 J2EE 使用 EJB 开发设计的优点及解决方案

​ Expert One-to-One J2EE Development without EJB(2004)

​ 阐述了 J2EE 开发不使用 EJB 的解决方式(Spring 雏形)

2017 年 9 月份发布了 spring 的最新版本 spring 5.0 通用版(GA)

发展优势

方便解耦,简化开发

通过 Spring 提供的 IoC 容器,可以将对象间的依赖关系交由 Spring 进行控制,避免硬编码所造 成的过度程序耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可 以更专注于上层的应用。

AOP 编程的支持

通过 Spring 的 AOP 功能,方便进行面向切面的编程,许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松应付。

声明式事务的支持

可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务的管理, 提高开发效率和质量。

方便程序的测试

可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可 做的事情。

方便集成各种优秀框架

Spring 可以降低各种框架的使用难度,提供了对各种优秀框架(Struts、Hibernate、Hessian、Quartz 等)的直接支持。

降低 JavaEE API******的使用难度

Spring 对 JavaEE API(如 JDBC、JavaMail、远程调用等)进行了薄薄的封装层,使这些 API 的 使用难度大为降低。

Java******源码是经典学习范例

Spring 的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对 Java 设计模式灵活运用以 及对 Java 技术的高深造诣。它的源代码无意是 Java 技术的最佳实践的范例。

通俗的说:

​ 使现有技术更加易用,推进编码最佳实践

​ 老技术新用法

​ 降低耦合性【亲密度】

七大部分组成

在这里插入图片描述

IoC容器【控制翻转/依赖注入】

AOP实现

数据访问支持

简化JDBC/ORM 框架

声明式事务

spring的web支持

spring的单元测试

Spring在mvc中的江湖位置:

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u8w5ZyGJ-1622703393122)(D:\王者班高级资料\笔记\02spring\typoraimg\wps2.jpg)]

耦合度

耦合度是再java中,类与类之间的关系,可以是 亲密度.

程序编程思想: 高内聚,低耦合

最好是再编译期不存在问题即可

public class TestJDBC {
    public static void main(String[] args) throws  Exception {
        // 加载驱动(使用Driver来创建该类的对象,放入到内存中)   关系: 非常亲密    高耦合
        // 降低耦合度     低耦合  解耦   : 使用反射机制来创建对象,并维护类与类之间的关系
        //DriverManager.registerDriver(new Driver());  // 硬编码
        Class.forName("com.mysql.jdbc.Driver");

        // 建立连接
        Connection connection = DriverManager.getConnection("jdbc:mysql:///duobiao", "root", "root");
        System.out.println( connection);
    }
}

工厂模式模仿spring的IOC

定义一个dao层并实现改层的方法(save() update() ),编写一个service层来调用dao层中的方法来实现功能.

UserDao.java

public interface UserDao {

    public void save();

    public void update();
    
}

UserDaoImpl.java

public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("----------添加数据(Mysql)----------");
    }

    @Override
    public void update() {
        System.out.println("=============修改数据(Mysql)========");
    }
}

UserOracleDaoIml.java

public class UserOracleDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("------添加数据(oracle)--------");
    }

    @Override
    public void update() {
        System.out.println("+++修改数据(oracle)+++");
    }
}

UserServer.java

public class UserService {
    // 使用servie中的业务方法来调用dao中的方法来使用
    //UserDao userDao = new UserDaoImpl();
    UserDao userDao = new UserOracleDaoImpl();
    // 分析缺点:  userServer和UserDao之间的耦合性较高    userDao不存在    硬编码方式
    //   解决 :  降低耦合  解耦   :   反射机制(BeanFactory)

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

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

UserUI.java

public class UserUI {

    public static void main(String[] args) {
        UserService userService = new UserService();

        userService.insert();

        userService.update();
    }
}

分析

​ 再UserServie中会发现,如果想要执行dao中的方法实现添加,那么必须使用 new 来创建userDao对象,如果连接不同的数据库,则 new 后的类也要随之改变,这种为***硬编码*方式,该方式不利于代码更改,类与类之间的耦合性较高,不符合"高内聚,低耦合"**的编程思想。

解决

​ 可以使用反射机制与工厂模式来创建一个工厂类,通过配置文件形式来搭建类与类之间的关系.使用反射机制的原来来代替原有的new来创建对象的过程。

BeanFactory.java

public class BeanFactory {

    private static Properties properties = new Properties();
    static{
        InputStream rs = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
        try {
            properties.load(rs);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 定义一个静态方法,来使用java的反射机制创建对象
    public static Object getInstance(String key){
        Object object = null;
        try {
            Class<?> ac = Class.forName(properties.getProperty(key));
            object = ac.newInstance();
        } catch (Exception e){
            e.printStackTrace();
        }
        return object;
    }
}

bean.properties

# key = value
userDao=cn.hd.dao.impl.UserOracleDaoImpl
userService=cn.hd.service.UserService

则userSercie中的对象创建就变为了以beanFactory的模式创建了

 //   解决 :  降低耦合  解耦   :   反射机制(BeanFactory)
 UserDao userDao = (UserDao) BeanFactory.getInstance("userDao");

UserUI中的创建userService的对象创建也变为了beanFactory的模式创建了

 public static void main(String[] args) {
        //UserService userService = new UserService();
        // 改变后
        UserService userService = (UserService) BeanFactory.getInstance("userService");
        userService.insert();
        userService.update();
    }

总结

​ 使用工厂模式和反射机制来实现以配置文件的形式创建对象的模式,可以释放类与类之间的耦合度,实现解耦

缺点

​ 类与类之间的关系还不能完全解耦,那么我们就可以学习使用spring框架来实现完全解耦了。

spring入门案例

实现步骤:

​ 1,再pom.xml文件中配置spring的核心jar包坐标

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

​ 2,再resoures下创建一个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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 创建一个UserDaoImpl的对象
		之前:
            UserDao userDao = new UserDaoImpl();
            userDao = cn.hd.dao.impl.UserDaoImpl  反射创建
         bean :  创建对象
            id : 创建对象后的唯一标识   对象名
            class : 类的全类名
            name : 创建对象后的对象名
            默认是使用无参的构造器创建对象,放入到IOC容器
            IOC : 反转控制    控制反转    创建对象
     -->
    <bean id="userDao" class="cn.hd.dao.impl.UserDaoImpl" ></bean>

    <bean id="ud" class="cn.hd.dao.impl.UserOracleDaoImpl"></bean>

    <bean name="userService" class="cn.hd.service.UserService"></bean>

</beans>

​ 3,编写测试类

@Test
    public void test1(){
        // 1,读取spring.xml配置,读取中或直接访问到bean标签,
        //      该标签就会把对应的对象创建成功,放入到spring的IOC容器中
        ClassPathXmlApplicationContext  cp = 
                    new ClassPathXmlApplicationContext("spring.xml");

        // 2,调用getBean("")从IOC容器中把userDao这个对象获取出来
        UserDao userDao = (UserDao) cp.getBean("userDao");

        System.out.println(userDao);
		//    根据目标资源类名来返回指定的对象
        UserService userService = cp.getBean("userService", UserService.class);
        System.out.println(userService);
    }

控制反转 IOC

IOC : 控制反转 创建对象 bean标签实现控制反转

​ 把java中创建对象的过程交给spring的核心配置文件【IOC容器】的过程

控制反转默认创建对象使用的是类的无参的构造器,创建后的对象的name/id名称必须唯一:

在这里插入图片描述

<!-- 创建一个UserDaoImpl的对象
            UserDao userDao = new UserDaoImpl();
            userDao = cn.hd.dao.impl.UserDaoImpl  反射创建
         bean :  创建对象
            id : 创建对象后的唯一标识   对象名
            class : 类的全类名
            name : 创建对象后的对象名
            默认是使用无参的构造器创建对象,放入到IOC容器
            IOC : 反转控制    控制反转    创建对象
     -->
    <bean id="userDao" class="cn.hd.dao.impl.UserDaoImpl"></bean>

    <bean id="ud" class="cn.hd.dao.impl.UserOracleDaoImpl"></bean>

    <bean name="userService" class="cn.hd.service.UserService"></bean>

scope属性

scope : 用来设置spring容器创建对象的模式

​ prototype : 多例模式 每一从使用getBean()都会创建一个新对象

​ 生命周期: 初始化 (init-method) 服务(getBean) 销毁(java垃圾回收处理)

​ singleton : 单例模式 读取配置文件是创建该类的唯一对象,放入IOC容器中

​ 生命周期: 初始化 (init-method) 服务(getBean) 销毁(destory-method)

配置文件:

<bean id="userDao" class="cn.hd.dao.impl.UserDaoImpl"
      scope="singleton" init-method="init" destroy-method="destory"></bean>

测试:

	@Test
    public void test3(){
        ClassPathXmlApplicationContext cp
                = new ClassPathXmlApplicationContext("spring.xml");

        UserDao userDao1 = cp.getBean("userDao", UserDao.class);
        System.out.println(userDao1);
        UserDao userDao2 = cp.getBean("userDao", UserDao.class);
        System.out.println(userDao2);
        UserDao userDao3 = cp.getBean("userDao", UserDao.class);
        System.out.println(userDao3);

        cp.close();
    }

数据输入 DI

DI : 依赖注入 属性赋值 property标签来实现依赖注入

​ 为IOC容器中所创建的对象的属性进行赋值的过程

IOC/DI : 控制反转,依赖注入

1,使用set注入数据

​ A,对象的依赖注入 ref

​ B,简单数据类型的依赖注入 (基本数据类型+String) value

​ Bean创建对象时,默认采用的是无参的构造器 在这里插入图片描述

2,使用有参的构造器注入数据

​ 首先要再类中定义一个有参的构造器:

在这里插入图片描述

​ 使用有参的构造器来创建对象并进行数据注入

在这里插入图片描述

3,使用p命令方式注入数据

注意:p标签模式注入,spring版本要再 5.xx 以上中使用

​ 现在spring.xml中定义p标签
在这里插入图片描述

​ 使用p标签实现数据注入

​ P:简单属性=”值” p:对象属性-ref=”对象名”

在这里插入图片描述

4,集合数据的注入

​ 定义一个类,声明一些集合属性

public class Student {

    private int arr[];
    private List list;
    private Map map;
    private Properties ps;

    @Override
    public String toString() {
        return "Student{" +
                "arr=" + Arrays.toString(arr) +
                ", list=" + list +
                ", map=" + map +
                ", ps=" + ps +
                '}';
    }
	// 省略公共的get和set方法
}

​ spring.xml中实现数据注入

 <bean name="student" class="cn.hd.service.Student">
        <property name="arr">
            <list>
                <value>1001</value>
                <value>1002</value>
            </list>
        </property>

        <property name="list">
            <list>
                <value>李四</value>
                <value>王五</value>
                <ref bean="ud"></ref>
            </list>
        </property>

        <property name="map">
            <map>
                <entry key="a" value="aaaa"/>
                <entry key-ref="ud" value="bbbb"/>
                <entry key-ref="ud" value-ref="ud"/>
                <entry key="b" value-ref="ud"/>
                <entry key="b" value="bbbb"/>
            </map>
        </property>

        <!--<property name="ps">
            <props>
                <prop key="a">aaaa</prop>
                <prop key="b">bbbb</prop>
            </props>
        </property>-->
        <property name="ps">
            <value>
                a=aaaaaa
                b=bbbbbbbbbbbbbbbbbbbbbbbbb
            </value>
        </property>

    </bean>

​ 运行并测试

	@Test
    public void test4(){
        ClassPathXmlApplicationContext cp
                = new ClassPathXmlApplicationContext("spring.xml");
       
        Student student = cp.getBean("student", Student.class);
        System.out.println(student.toString());

    }

注解实现IOC/DI

再项目中如果有多张表的操作,则dao层和service创建对象和赋值的过程中会创建多个bean标签,该标签再spring.xml中就会有很多个,看着不合适,编写较为麻烦。

咱们就可以使用spring提供的注解来实现 IOC / DI

常见注解:

​ 注解方式将Bean的定义信息和Bean实现类结合在一起,Spring提供的注解有

​ @Component:实现Bean组件的定义,创建对象

​ @Repository :用于标注DAO类 创建对象 继承@Component

​ @Service :用于标注业务类 创建对象 继承@Component

​ @Controller :用于标注控制器类 创建对象 继承@Component

@Scope(value=“singleton/prototype”) 设置创建对象的模式(单例/多例)

使用@Autowired注解实现Bean的自动装配,默认按类型匹配,可以使用@Qualifier指定Bean的名称

注意: 注解形式可以省略get和set方法

​ @Value 为简单类型注入数据

​ @Atuowired 自动装配

​ @Qualifier(value="") 与@Autowired结合使用

​ @Resource(name = “ud”) 根据name的名称实现数据注入

案例1:

​ 1,再spring的配置文件头部引入context标签的支持

在这里插入图片描述

​ 2,再配置文件中配置扫描包

在这里插入图片描述

​ 3,再每一个类前加入指定的注解

在这里插入图片描述

在这里插入图片描述

​ 4,再类中的属性中使用注解实现数据注入

在这里插入图片描述

​ 5,测试类

在这里插入图片描述

案例2:

​ 使用注解方式动态的从db.properties的配置文件中动态的获取连接数据库的四大组件值:

​ 1,创建db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///test
name=root
pwd=123456

​ 2,再配置文件中读取配置文件

<!-- 如果使用注解,则我们需要再spring.xml配置文件中,实现扫描包的配置
        自动扫描类前@component注解实现创建对象
        并扫描创建中的DI的注解实现数据的注入-->
    <context:component-scan base-package="cn.hd" />

    <!-- 引入外部配置文件 -->
    <context:property-placeholder location="classpath:db.properties"/>

​ 3,再类中使用@Value动态的实现数据注入

@Component(value = "jdu")
public class JDBCUtils {
        @Value("${driver}")
        private  String driver ;
        @Value("${url}")
        private String url ;
        @Value("${name}")
        private String username ;
        @Value("${pwd}")
        private String password ;


        @Override
    public String toString() {
        return "JDBCUtils{" +
                "driver='" + driver + '\'' +
                ", url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

​ 4,测试

@Test
public void test2(){
   ClassPathXmlApplicationContext cp
                = new ClassPathXmlApplicationContext("spring.xml");
   JDBCUtils jdu = cp.getBean("jdu", JDBCUtils.class);

   System.out.println(jdu.toString());
 }

总结:

​ 1,如果是自己编写的java类,需要spring来统一管理,一般采用注解

​ 2,如果是调用框架中封装好的功能组件,一般我们采用xml配置形式

​ 3,注解方式一般改变都要重启,xml方式一旦数据注入,就要提供公共的get和set方法

spring的单元测试

spring整合的junit的单元测试后,每一次的调用都不需要再去直接读取配置文件了。

使用spring的测试有利于后期整合项目的单独测试,便于开发。

使用步骤:

​ 1,导入spring-test包

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

​ 2,导入junit包 注意: 如果spring的是5.xxx以上,则junit必须是 4.12以上版本

		<dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

​ 3,再测试类中配置即可

// 把单元测试的功能交给了spring中整合的单元测试
@RunWith(SpringJUnit4ClassRunner.class)
// 读取spring.xml的核心配置文件,该IOC容器作用域整个类
@ContextConfiguration(locations = "classpath:spring.xml")
public class TestSpring2 {
    @Autowired
    private JDBCUtils jd;
    @Autowired
    private UserDao userDao;
    @Autowired
    private UserService userService;
    @Test
    public void t1(){
        System.out.println(jd.toString());
    }

    @Test
    public void t2(){
        userDao.save();
    }
    @Test
    public void t3(){
        System.out.println(userService.toString());
    }
}

spring配置文件的拆分

以后我们想要编写项目时,需要再spring.xml中配置很多的文件信息,如果把所有的文件信息全部都配置到一个配置文件中,该文件就会很大,不利于项目的配置文件的拷贝。

再核心配置文件中引入另一个配置文件:

<!-- 引入另一个spring的配置文件 -->
<import resource="classpath:spring-db.xml"/>

AOP 面向切面编程

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

通俗说:面向切面编程,切面类,把通用的功能提取出来放入到一个类,该类再不同的功能中被多次的调用并使用,那么该类就是切面类。各个功能再经过了该切面类后,其功能就会实现(功能)增强,实现代码的可重用性.

作用:

​ 在程序运行期间,不修改源码对已有方法进行增强。

优势:

​ 减少重复代码

​ 提高开发效率

​ 维护方便

画图理解:

在这里插入图片描述

springAOP的知识点

*Joinpoint(********连接点********)😗

所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的

连接点。

*Pointcut(********切入点********)😗

所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义。

*Advice(********通知********/********增强********)😗

所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。

通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。

*Target(********目标对象********)😗

代理的目标对象。

*Weaving(********织入********)😗

是指把增强应用到目标对象来创建新的代理对象的过程。

spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。

*Proxy********(代理)********😗

一个类被 AOP 织入增强后,就产生一个结果代理类。

*Aspect(********切面********)😗

是切入点和通知(引介)的结合。

xml配置文件实现AOP

1,导入jar包 【spring-aop aspectjweaver 】

在这里插入图片描述

2,再spring.xml中配置AOP即可

在这里插入图片描述

3,测试

在这里插入图片描述

4,结果

在这里插入图片描述

优化:

​ 1,可以直接把切入点表达式提取出来

​ 2,加入不同的增强方式:

​ 前置增强 before 再方法前先执行

​ 后置增强 afterReturnning 方法没有异常时执行

​ 异常增强 afterThrowing 方法中有异常时执行

​ 最终增强 after 不论方法是否有异常,都要执行

​ 环绕增强 around 再方法的前后执行,类似前置增强和最终增强的结合体

<aop:config proxy-target-class="true">
        <!-- 配置切入点 -->
        <aop:aspect ref="log">
            <!--   aop:before : 设置前置增强   method:指向切面类的方法名
            pointcut : 切入点   表达式:execution( public * cn.hd.XAOP.UserServiceImpl.save() )
                    public * cn.hd.XAOP.UserServiceImp.*(..)
                    public * cn.hd.XAOP.*.*(..)    XAOP下的所有的类的方法
                    public * cn.hd.XAOP..*.*(..)   XAOP下的所有的类及其子包中的所有的类
                -->
            <aop:pointcut id="pt" expression="execution(public * cn.hd.XAOP.UserServiceImpl.*(..))"></aop:pointcut>
            <aop:before method="before" pointcut-ref="pt"></aop:before>
            <aop:after method="after" pointcut-ref="pt"></aop:after>
            <aop:after-returning method="afterrunning" pointcut-ref="pt"></aop:after-returning>
            <aop:after-throwing method="afterThrowing" pointcut-ref="pt"></aop:after-throwing>

        </aop:aspect>
    </aop:config>

注解来实现AOP

​ @Aspect 定义类为切面类

​ @Pointcut 定义方法为切入点

​ @Before 定义方法为前置增强

​ @After 定义方法为最终增强

​ @Afterreturnning 定义方法为后置增强

​ @Afterthrowing 定义方法为异常增强

​ @Around 定义方法为环绕增强

配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 扫描包来创建对应的对象 -->
    <context:component-scan base-package="cn.hd.ann"></context:component-scan>
    <!--  启动动态代理       来读取代理类中的注解 -->
    <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
</beans>

切面类:

@Component    // 创建对象放入IOC容器
@Aspect		  // 定义该类是切面类
public class LogAdvice {  // 创建对象    切面类
    // 定义切入点方法
    @Pointcut("execution(public * cn.hd.ann.UserServiceImpl.*(..))")
    public void pt(){ }
    // 前置增强
    @Before("pt()")
    public void before(){
        System.out.println("==开启日志系统=======");
    }
    // 最终增强     不论是否有异常,都要执行
    @After("pt()")
    public void after(){
        System.out.println("==关闭日志系统=======");
    }
    //  异常增强   -- 有异常的时候才执行
    @AfterThrowing("pt()")
    public void afterThrowing(){
        System.out.println("--------异常增强------------");
    }
    // 后置增强     没有异常时才执行
    @AfterReturning("pt()")
    public void afterrunning(){
        System.out.println("---------后置增强--------------");
    }
}

spring提供的JDBCTemplate

​ jdbcTemplate是spring对java访问数据库技术的JDBC进行了简单的封装,封装后,我们使用该组件来访问数据库时就会提高访问效率,提高开发效率,访问时也会对不同的数据进行封装(对象).

​ Spring对数据库的操作在jdbc上面做了深层次的封装,使用Spring的注入功能,可以把DataSource(数据库连接池)注册到jdbcTemplate中

常见方法:

​ update (更新数据)

​ batchUpdate (批量更新数据库)

​ queryForObject (查询单行)

​ query (查询多行)

使用步骤:

​ 0,准备工作

​ 创建一个表,编写其实体类

在这里插入图片描述

在这里插入图片描述

​ 1,导入spring-jdbc的jar包和spring-tx的jar包

在这里插入图片描述

​ 2,再测试类中直接使用JDBCTemplate对象来连接数据库访问即可

@Test
    public void t1(){
        // 创建数据对象,并设置参数
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///springdemo");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        // 1,创建jdbcTemplate对象
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        // 2,为jdbcTemplate对象设置数据源( 驱动  url   username  password )
        jdbcTemplate.setDataSource(dataSource);
        // 3,直接使用update方法来操作了
        int num = jdbcTemplate.update("insert into user values(null,?,?,?)", "李四", "男", 23);

        System.out.println(num);
    }

优化

我们可以把创建datasource和jdbctemplate的过程全部交给sprig的配置文件来统一处理:

db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///springdemo
name=root
password=root

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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    
    <context:property-placeholder location="classpath:db.properties"/>
    <!-- 创建数据源对象 -->
    <bean id="ds" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${driver}"></property>
        <property name="url" value="${url}"></property>
        <property name="username" value="${name}"></property>
        <property name="password" value="${password}"></property>
    </bean>
    <!-- 创建jdbcTemplate对象 -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="ds"></property>
    </bean>

</beans>

测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring.xml")
public class TestJDBC {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    // 添加数据
    @Test
    public void add(){
        Object obj[] = {"王五","男",22};
        int num = jdbcTemplate.update("insert into user values(null,?,?,?)", obj);
        System.out.println(num);
    }
	// 删除数据
    @Test
    public void delete(){
        int num = jdbcTemplate.update("delete from user where id=?", 1);
        System.out.println(num);
    }
    // 查询所有的数据
    @Test
    public void selectAll(){
        List<User> query = jdbcTemplate.query("select *  from user", 
                                              new BeanPropertyRowMapper<>(User.class));
        for (User us : query){
            System.out.println(us.toString());
        }
    }
    // 根据id查询数据
    @Test
    public void selectById(){
        User user = jdbcTemplate.queryForObject("select * from user where id=?",
                                           new BeanPropertyRowMapper<>(User.class), 2);
        System.out.println(user.toString());
    }
    // 查询总条数
    @Test
    public void selectCount(){
        Integer count = jdbcTemplate.queryForObject("select count(1) from user", 
                                                    int.class);
        System.out.println(count);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值