SpringBoot下的Spring框架学习(tedu)——day03——Spring DI、SpringAOP JDK动态代理

news2025/1/30 16:26:48

SpringBoot下的Spring框架学习(tedu)——day03——Spring DI、SpringAOP JDK动态代理

目录

  • SpringBoot下的Spring框架学习(tedu)——day03——Spring DI、SpringAOP JDK动态代理
  • 1. Spring的依赖注入
    • 1.1 依赖注入案例
      • 1.1.1 定义接口Pet
      • 1.1.2 定义Dog类
      • 1.1.3 定义User类
      • 1.1.4 编辑配置类
      • 1.1.5 编辑测试代码
      • 1.1.6 测试结果
      • 1.7 结果的流程分析(重要)
    • 1.2 多实现类案例讲解
      • 1.2.1 关于案例说明
    • 1.3 MVC 设计思想
      • 1.3.1 传统代码结构
      • 1.3.2 MVC设计思想说明
      • 1.3.3 "三层"代码结构
    • 1.4 "三层"代码结构实现
      • 1.4.1 代码结构说明
      • 1.4.2 编辑Mapper
      • 1.4.3 编辑Service
      • 1.4.4 编辑Controller
      • 1.4.5编辑配置类
      • 1.4.6 编辑测试类
      • 1.4.7 测试结果
    • 1.5 @Value注解
      • 1.5.1 编辑properties文件
      • 1.5.2 编辑UserMapper
      • 1.5.3 编辑UserMapperImpl
      • 1.5.4 编辑测试类
      • 1.5.5 关于IOC-DI总结
    • 2. Spring-AOP
      • 2.1 创建新项目
      • 2.2.2 关于代理模式说明
      • 2.2.3 动态代理-JDK动态代理
      • 2.2.4 业务代码测试
      • 2.2.5 测试结果
      • 2.2.6 问题:为什么 System.out.println(proxy);会打印事务开始和事务结束?
  • 常用注解

1. Spring的依赖注入

1.1 依赖注入案例

1.1.1 定义接口Pet

package com.jt.demo8;

public interface Pet {

    void hello();

}

1.1.2 定义Dog类

package com.jt.demo8;

import org.springframework.stereotype.Component;

@Component //将该类交给Spring容器管理 key:dog(当前类别首字母小写),value:反射机制创建对象
public class Dog implements Pet{

    public Dog(){
        System.out.println("Dog的无参构造");
    }

    @Override
    public void hello() {
        System.out.println("小狗汪汪汪!!!");
    }
}

1.1.3 定义User类

package com.jt.demo8;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component//将User对象交给Spring容器管理
public class User {

    public User(){
        System.out.println("我是User的无参构造");
    }

    /**
     * 注入:将spring容器中的对象进行引用
     * @Autowired: 可以将容器中对象进行注入
     *      1.按照类型注入
     *          如果注入的类型是接口,则自动的查找其实现类对象进行注入
     *          注意事项:一般spring框架内部的接口都是单实现,特殊条件下可以多实现
     *      2.按照名称注入
     */
    @Autowired
    private Pet pet;

    public void hello(){
        pet.hello();
    }


}


1.1.4 编辑配置类

package com.jt.demo8;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@ComponentScan("com.jt.demo8")
@Configuration
public class SpringConfig {

}

1.1.5 编辑测试代码

package com.jt.demo8;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class SpringDI {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        User user = applicationContext.getBean(User.class);
        user.hello();
    }
}

1.1.6 测试结果

在这里插入图片描述

1.7 结果的流程分析(重要)

Spring容器启动,加载配置类SpringConfig;
配置类SpringConfig扫描包,全局扫描,扫描到dog类;
把dog类利用反射的机制,创建对象,会调用dog的无参构造方法;
key指定为dog(当前类名小写),value:反射机制创建的对象
继续扫描,扫描到User类,
扫描到@Autowired,找到Pet接口的实现类dog,并注入给User的pet属性
把User交给Spring容器管理

1.2 多实现类案例讲解

1.2.1 关于案例说明

一般条件下 Spring中的接口,都是单实现,如果遇到多实现,则如图所示
在这里插入图片描述
由于没有做其它操作,所以程序必然报错.
在这里插入图片描述
异常解决:
User.java
在这里插入图片描述

1.3 MVC 设计思想

1.3.1 传统代码结构

说明: 如果将所有的业务代码都写到一个方法中,则导致后期维护耦合性高,为了提高程序的扩展性.将程序按照MVC设计思想 进行管理.

1.3.2 MVC设计思想说明

M: Model 数据层
V: View 视图层
C: Control 控制层
总结: MVC 主要的目的降低代码的耦合性,提高扩展性.方便后续开发.
在这里插入图片描述

1.3.3 "三层"代码结构

说明: 基于MVC设计思想的启发,在后端为了提高代码的扩展性,一般将后端代码分为三层.
分层:

  1. Controller层 主要与页面进行交互 @Controller
  2. Service层 主要实现后端的业务逻辑 @Service
  3. Dao层/Mapper层 主要与数据库进行交互 也把该层称之为 “持久层” @Repository/@Mapper

1.4 "三层"代码结构实现

1.4.1 代码结构说明

包名: mapper 类2个 一个接口UserMapper/一个实现类 UserMapperImpl
包名: service 类2个 一个接口UserService/ 一个实现类UserServiceImpl
包名: controller 一个类: UserController
知识说明: 被调用的一般会有接口和实现类

1.4.2 编辑Mapper

1.编辑UserMapper

package com.jt.demo9.mapper;

public interface UserMapper {

    void addUser();

}

2.编辑Mapper 实现类

package com.jt.demo9.mapper;

import org.apache.catalina.User;
import org.springframework.stereotype.Repository;

@Repository//表示持久层 该类交给Spring容器管理 key:userMapperImpl value:对象
public class UserMapperImpl implements UserMapper {
    @Override
    public void addUser() {
        System.out.println("新增用户成功!!!!");
    }
}

1.4.3 编辑Service

  1. 编辑UserService
package com.jt.demo9.service;

public interface UserService {
    void addUser();
}

2.编辑UserServiceImpl

package com.jt.demo9.service;

import com.jt.demo9.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService{

    @Autowired
    private UserMapper userMapper;//IOC+DI 解耦!!!!

    @Override
    public void addUser() {
        userMapper.addUser();
    }
}

1.4.4 编辑Controller

package com.jt.demo9.controller;

import com.jt.demo9.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller//key=userController
public class UserController {

    @Autowired
    private UserService userService;

    public void addUser(){
        userService.addUser();
    }
}

1.4.5编辑配置类

package com.jt.demo9.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@ComponentScan("com.jt.demo9")
@Configuration
public class SpringConfig {



}

1.4.6 编辑测试类

package com.jt.demo9;

import com.jt.demo9.config.SpringConfig;
import com.jt.demo9.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Spring_MVC {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserController userController = applicationContext.getBean(UserController.class);
        userController.addUser();
    }

}

1.4.7 测试结果

在这里插入图片描述

1.5 @Value注解

1.5.1 编辑properties文件

# 1.数据结构 key=value
# 2.无需添加多余的引号
# 3.注意多余的空格
# 4.程序读取properties文件时,默认采用ISO-8859-1编码!中文必定乱码
name=张三

1.5.2 编辑UserMapper

package com.jt.demo10.mapper;

public interface UserMapper {
    void addUser();
}

1.5.3 编辑UserMapperImpl

package com.jt.demo10.mapper;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Repository;

//Spring根据指定的路径,加载properties配置文件 数据添加到Spring容器中
@PropertySource(value = "classpath:/addUser.properties",encoding = "UTF-8")
@Repository
public class UserMapperImpl implements UserMapper{

    /**
     * @Value 注解的作用:为属性赋值
     *        需求:从Spring容器中动态获取数据
     */

    //@Value("张三")//直接写法,扩展性不好
    @Value("${name}")
    private String name;

    @Override
    public void addUser() {
        System.out.println("新增用户:"+name);
    }
}


1.5.4 编辑测试类

package com.jt.demo10;

import com.jt.demo10.config.SpringConfig;
import com.jt.demo10.mapper.UserMapper;
import com.jt.demo10.mapper.UserMapperImpl;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class SpringValue {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        //获取的对象 实现类和接口都可以
//        UserMapper userMapper = applicationContext.getBean(UserMapperImpl.class);
        UserMapper userMapper = applicationContext.getBean(UserMapper.class);
        userMapper.addUser();
    }
}

1.5.5 关于IOC-DI总结

  1. 什么是IOC: 控制反转, 将对象交给Spring容器管理,由容器管理对象的生命周期.
  2. 什么是DI: 依赖注入 为当前对象注入属性(属性也是对象).
  3. 扩展问题: 如果采用配置文件xml的方式进行注入,则注入的方式有多种.
    ①set方式注入
    ②构造方法注入
    ③工厂模式注入

总结: 使用IOC-DI可以极大程度上实现代码的松耦合(解耦)

2. Spring-AOP

2.1 创建新项目

在这里插入图片描述
2. 勾选jar包
在这里插入图片描述
2.2 AOP代码铺垫
2.2.1 业务说明
事务特性: 1. 原子性 2. 一致性 3.隔离性 4.持久性
业务说明: 在增/删除/修改的操作过程中添加事务控制.

Demo效果演示
配置类

package com.jt.demo1.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@ComponentScan("com.jt.demo1")
@Configuration
public class SpringConfig {

}

Service层
service层接口

package com.jt.demo1.service;

public interface UserService {
    void addUser();
    void deleteUser();
}

service层实现类

package com.jt.demo1.service;

import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

    @Override
    public void addUser() {
        System.out.println("完成用户新增");
    }

    @Override
    public void deleteUser() {
        System.out.println("完成用户删除操作");
    }
}

测试类

package com.jt.demo1;

import com.jt.demo1.config.SpringConfig;
import com.jt.demo1.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class SpringTx {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserService userService = applicationContext.getBean(UserService.class);
        userService.addUser();
        userService.deleteUser();
    }
}

demo2
service层实现类

package com.jt.demo1.service;

import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

    @Override
    public void addUser() {
        try {
            System.out.println("事务开始");
            System.out.println("完成用户新增");
            System.out.println("事务提交");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("事务回滚");
        }
    }

    @Override
    public void deleteUser() {
        try {
            System.out.println("事务开始");
            System.out.println("完成用户删除操作");
            System.out.println("事务提交");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("事务回滚");
        }
    }
}

结论:

  1. 如果按照上述的代码进行编辑,则所有增/删除/修改操作的代码都必须按照上述的规则.那么代码冗余.
  2. UserService与事务控制代码紧紧的耦合在一起.不方便后期扩展. 以后尽可能保证业务的纯粹性.

2.2.2 关于代理模式说明

说明: 在业务层不方便做,但是又不得不做的事情,可以放到代理对象中. 通过这样的设计就可以解决业务层耦合的问题. 代理对象看起来和真实的对象 一模一样.所以用户使用不会察觉.
在这里插入图片描述
类比:

  1. 外卖也是一种典型的代理思想
  2. 游戏代练
  3. 房屋中介

2.2.3 动态代理-JDK动态代理

demo3

在demo1上面的基础之上,创建一个proxy包,里面创建一个JDKProxy类

package com.jt.demo1.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JDKProxy {

    /**
     * 获取代理对象
     * 参数说明:
     * 1.ClassLoader loader     类加载器 读取真实的类数据
     * 2.Class<?>[] interfaces  要求传递接口的信息
     * 3.InvocationHandler h    当代理对象执行方法时执行
     * 注意事项:JDK代理必须要求 “被代理者” 有接口要么实现接口
     *
     * @param target
     * @return
     */
    public static Object getProcy(Object target){
        //1.获取类加载器
        ClassLoader classLoader = target.getClass().getClassLoader();
        //2.获取接口
        Class<?>[] interfaces = target.getClass().getInterfaces();

        //通过代理的类新创建一个代理的对象
        return Proxy.newProxyInstance(classLoader, interfaces, getInvocationHandler(target));


    }

    //代理对象执行方法时调用
    public static InvocationHandler getInvocationHandler(Object target){
        //这些代码都是写死的
        return new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("================事务开始==============================");
                //执行目标(真实对象的)方法
                Object result = method.invoke(target, args);
                System.out.println("=========================事务提交=======================");
                return result;
            }
        };
    }



}


2.2.4 业务代码测试

package com.jt.demo1;

import com.jt.demo1.config.SpringConfig;
import com.jt.demo1.proxy.JDKProxy;
import com.jt.demo1.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class SpringTx {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserService userService = applicationContext.getBean(UserService.class);
        System.out.println(userService.getClass());

        UserService proxy = (UserService)JDKProxy.getProcy(userService);
        System.out.println(proxy.getClass());

        System.out.println(proxy);
        System.out.println(proxy.toString());

        //基于代理对象,执行业务操作 实现方法扩展
        proxy.addUser();
        proxy.deleteUser();
    }
}

2.2.5 测试结果

在这里插入图片描述

2.2.6 问题:为什么 System.out.println(proxy);会打印事务开始和事务结束?

因为它默认打印的是proxy.toString方法,即调用了被代理类的toString方法,所以会打印事务开始和事务结束,以及其地址信息。

常用注解

@Configuration 标识当前类是配置类
@ComponentScan 包扫描注解 扫描注解
@Bean 标识该方法的返回值交给Spring容器管理
@Scope 控制多例和单例
@Lazy 懒加载
@PostConstruct 初始化方法
@PreDestroy 销毁方法
@Component 将当前类未来的对象交给容器管理
@Autowired 按照类型进行注入
@Qualifier 按照名称进行注入
@Repository 标识持久层注解
@Service 标识Service层
@Controller 标识Controller层
@Value 为属性赋值 @Value("${key}")
@PropertySource 加载指定路径的配置文件properties

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/396633.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python的运算符

Python支持多种运算符&#xff0c;下表大致按照优先级从高到低的顺序列出了所有的运算符&#xff0c;运算符的优先级指的是多个运算符同时出现时&#xff0c;先做什么运算然后再做什么运算。除了我们之前已经用过的赋值运算符和算术运算符&#xff0c;我们稍后会陆续讲到其他运…

解决launch:program .exe does not exist

二. 程序的运行和调试 1.launch.json 复制下列代码至launch.json&#xff0c;并根据指导做出相对/绝对路径修改 用 IntelliSense 了解相关属性。 {// 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。// 欲了解更多信息&#xff0c;请访问: https://go.micros…

虹科教您 | 在Linux环境下安装PCAN View及通讯测试指南

应用简介 PCAN-View软件是一款简化的CAN监视软件&#xff0c;可用于显示、发送、和记录CAN数据通讯。报文可手动和定期发送&#xff0c;用户可设置比特率。在处理期间显示总线系统错误和CAN硬件的存储器过满。示踪功能可用于记录和保存CAN数据通讯。本文档的作用在于&#xff…

Python进阶-----面向对象8.0(反射---对象属性方法操作)

目录 前言&#xff1a; 反射 1.getattr() 函数 2.setattr() 函数 3.hasattr() 函数 4.delattr() 函数 前言&#xff1a; 众所周知&#xff0c;每一个实例化对象都是有实例化属性或者方法的&#xff0c;之前我们对实例化对象进行属性方法查询、删除或者添加都是直接去通过…

day27_css

今日内容 上课同步视频:CuteN饕餮的个人空间_哔哩哔哩_bilibili 同步笔记沐沐霸的博客_CSDN博客-Java2301 零、 复习昨日 一、CSS 零、 复习昨日 见代码 一 、引言 1.1CSS概念 ​ 层叠样式表(英文全称&#xff1a;Cascading Style Sheets)是一种用来表现HTML&#xff08;标准通…

MpAndroidChart3最强实践攻略

本篇主要总结下Android非常火爆的一个三方库MpAndroidChart的使用。可能在大多数情况下&#xff0c;我们很少会在Android端去开发图表。但如果说去做一些金融财经类、工厂类、大数据类等的app&#xff0c;那么绝对会用到MpAndroidChart。 一、前言 2018年&#xff0c;那年的我…

打包成JAR文件和WAR文件,到底有什么区别?

Spring Boot是一种基于Spring框架的快速开发应用程序的工具&#xff0c;可以轻松地构建可部署的独立应用程序。在使用Spring Boot时&#xff0c;你可能会注意到有两种不同的部署选项&#xff1a;打包成JAR文件和WAR文件。在这篇文章中&#xff0c;我们将深入探讨这两种部署选项…

Netty 简介

一、Netty 简介 Netty 是基于 Java NIO 的异步事件驱动的网络应用框架&#xff0c;使用 Netty 可以快速开发网络应用&#xff0c;Netty 提供了高层次的抽象来简化 TCP 和 UDP 服务器的编程&#xff0c;但是你仍然可以使用底层的 API。 Netty 的内部实现是很复杂的&#xff0c;但…

Mysql常见的函数介绍

Mysql查询示例简介一、创建计算字段二、使用数据处理函数1. 文本处理函数2. 日期和时间处理函数3. 数值处理函数三、聚集函数总结简介 本篇博客中介绍了mysql查询时&#xff0c;常用的一些函数&#xff0c;融会贯通这些函数的使用&#xff0c;会对工作和学习有很大的帮助&#…

【软考中级信安】第四章--网络安全体系与网络安全模型

1.网络安全体系概述1.1 网络安全体系概念网络安全体系&#xff1a;是网络安全保障系统的最高层概念抽象&#xff0c;是由各种网络安全单元按照一定的规则组成的&#xff0c;共同实现网络安全的目标。1.2 网络安全体系特性整体性&#xff1a;网络安全单元按照一定规则&#xff0…

SequoiaDB分布式数据库2023.2月刊

本月看点速览 技术实力获认可&#xff0c;获评多项荣誉 共建人才生态&#xff0c;与深圳大学举办奖学金颁奖仪式 青杉计划2023持续进行&#xff0c;一起攀登更高的“杉” 技术实力获认可&#xff0c;获评多项荣誉 2月&#xff0c;21世纪创投研究院发布“21世纪&#xff08;全…

【20230308】串口接收数据分包问题处理(Linux)

1 问题背景 一包数据可能由于某些传输原因&#xff0c;经常出现一包数据分成几包的情况。 2 解决方法 2.1 通过设定最小读取字符和读取超时时间 可以使用termios结构体来控制终端设备的输入输出。可以通过VTIME和VMIN的值结合起来共同控制对输入的读取。此外&#xff0c;两…

[2.2.1]进程管理——调度的概念、层次

文章目录第二章 进程管理调度的概念、层次&#xff08;一&#xff09;调度的基本概念&#xff08;二&#xff09;调度的三个层次&#xff08;1&#xff09;高级调度&#xff08;2&#xff09;低级调度&#xff08;3&#xff09;中级调度补充知识&#xff1a;进程的挂起态与七状…

第三篇:字符显示原理

使用PCtolLCD2003制作字库注意,我们开始取模前一定要记得设置取模方式,这个取模方式和我们显示屏的显示方式要一致设置字体为宋体,字体大小为16*16(这里当然可以设为别的)输入想要显示的字点击生成字模u8 shuai[] {0x10,0x04,0x10,0x04,0x12,0x04,0x12,0x04,0x92,0x3F,0x92,0x…

HTML 编辑器

文章目录 HTML 编辑器HTML 编辑器推荐编辑器下载网站HBuilder步骤 1: 新建 HTML 文件步骤 2: 另存为 HTML 文件步骤 3: 在浏览器中运行这个 HTML 文件HTML 编辑器 HTML 编辑器推荐 可以使用专业的 HTML 编辑器来编辑 HTML,我为大家推荐几款常用的编辑器: Notepad++:Windows…

蓝桥dfs专题

1、dfs 路径打印 小明冒充X星球的骑士&#xff0c;进入了一个奇怪的城堡。 城堡里边什么都没有&#xff0c;只有方形石头铺成的地面。 假设城堡地面是 n x n 个方格。【如图1.png】所示。 按习俗&#xff0c;骑士要从西北角走到东南角。 可以横向或纵向移动&#xff0c;但不能…

SpringBoot基础知识

1 SpringBoot简介1.1 入门官网创建SpringBoot项目&#xff1a;https://start.spring.io/快速启动SpringBoot工程&#xff1a;SpringBoot程序可以不依赖Tomcat和IDE&#xff0c;源码工程打完jar后可以直接运行。java -jar springboot_quick_start-0.0.1-SNAPSHOT.jar1.2 简介<…

OAK相机如何将yoloV5lite模型转换成blob格式?

编辑&#xff1a;OAK中国 首发&#xff1a;oakchina.cn 喜欢的话&#xff0c;请多多&#x1f44d;⭐️✍ 内容可能会不定期更新&#xff0c;官网内容都是最新的&#xff0c;请查看首发地址链接。 ▌前言 Hello&#xff0c;大家好&#xff0c;这里是OAK中国&#xff0c;我是助手…

Hadoop 使用Linux操作系统与Java熟悉常用的HDFS操作

注意看评论区获取完整代码资料 目录 一、实验目的 二、实验平台 三、实验步骤 一、实验目的 理解HDFS在Hadoop体系结构中的角色&#xff1b;熟练使用HDFS操作常用的Shell命令&#xff1b;熟悉HDFS操作常用的Java API。 二、实验平台 操作系统&#xff1a;Linux&#xff0…

运筹系列68:TSP问题Held-Karp下界的julia实现

1. 介绍 Held-Karp下界基于1tree下界&#xff0c;但是增加了点权重&#xff0c;如下图 通过梯度下降的方法找到最优的π\piπ。 这里用到的1tree有下面几种&#xff1a; 全部点用来生成最小生成树&#xff0c;再加上所有叶子结点第二短的边中数值最大的那个任意选一个点&…