Spring底层机制环境搭建

news2024/11/20 2:19:27

文章目录

    • 1.模块创建和依赖引入
        • 1.聚合模块,下面有一个myspring
        • 2.查看父模块是否管理了子模块
        • 3.myspring模块引入基本包
    • 2.进行环境搭建
        • 1.目录概览
        • 2.UserController.java
        • 3.UserService.java
        • 4.UserDao.java
        • 5.AppMain.java
        • 6.beans.xml
        • 7.测试
        • 8.配置UserController.java为多例的,然后测试
        • 9.UserService调用add方法,然后测试
        • 10.引入Bean后置处理器
          • 1.位置
          • 2.MyBeanPostProcessor.java
          • 3.UserService.java 设置初始化方法
          • 4.beans.xml配置扫描
          • 5.测试
          • 6.注意事项
        • 11.引入AOP
          • 1.目录
          • 2.SmartAnimal.java
          • 3.SmartDog.java
          • 4.SmartAnimalAspect.java
          • 5.beans.xml开启aop注解并扫描aop包
          • 6.AppMain.java 测试AOP
          • 6.简单分析AOP和后置处理器的关系
    • 3.抛出问题
        • 1.bean是怎么注入容器的?
        • 2.为什么加了@Autowired就能被依赖注入?
        • 3.单例多例是怎么实现的?
        • 4.Bean的后置处理器是怎么实现的?
        • 5.原生Spring的AOP是如何实现的?
    • 4.将代码放到远程仓库
        • 1.VCS -》 share
        • 2.查看仓库

1.模块创建和依赖引入

1.聚合模块,下面有一个myspring

CleanShot 2024-08-04 at 13.50.33@2x

2.查看父模块是否管理了子模块

CleanShot 2024-08-04 at 13.51.05@2x

3.myspring模块引入基本包
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.8</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.3.8</version>
    </dependency>
</dependencies>

2.进行环境搭建

1.目录概览

CleanShot 2024-08-04 at 14.06.39@2x

2.UserController.java
package com.sunxiansheng.myspring.component;

import org.springframework.stereotype.Component;

/**
 * Description: 就是一个Controller组件
 * @Author sun
 * @Create 2024/8/4 13:53
 * @Version 1.0
 */
@Component
public class UserController {
}
3.UserService.java
package com.sunxiansheng.myspring.component;

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

/**
 * Description: 一个Service组件
 * @Author sun
 * @Create 2024/8/4 13:54
 * @Version 1.0
 */
@Component
public class UserService {

    /**
     * 依赖注入UserDao
     */
    @Autowired
    private UserDao userDao;

    public void add() {
        System.out.println("UserService 调用了UserDao的add方法");
        userDao.add();
    }

}
4.UserDao.java
package com.sunxiansheng.myspring.component;

import org.springframework.stereotype.Component;

/**
 * Description: 一个Dao组件
 * @Author sun
 * @Create 2024/8/4 13:53
 * @Version 1.0
 */
@Component
public class UserDao {

    public void add() {
        System.out.println("UserDao add...");
    }

}
5.AppMain.java
package com.sunxiansheng.myspring;

import com.sunxiansheng.myspring.component.UserController;
import com.sunxiansheng.myspring.component.UserDao;
import com.sunxiansheng.myspring.component.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Description: 启动类
 * @Author sun
 * @Create 2024/8/4 13:59
 * @Version 1.0
 */
public class AppMain {

    public static void main(String[] args) {
        // 从类路径下加载beans.xml配置文件
        ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
        // 从容器中获取UserController对象,这里获取两次,看是否是同一个对象
        UserController userController1 = (UserController) ioc.getBean("userController");
        UserController userController2 = (UserController) ioc.getBean("userController");
        System.out.println("userController1 == userController2 ? " + (userController1 == userController2));
        // 从容器中获取UserService对象
        UserService userService = (UserService) ioc.getBean("userService");
        System.out.println("userService = " + userService);
        // 从容器中获取UserDao对象
        UserDao userDao = (UserDao) ioc.getBean("userDao");
        System.out.println("userDao = " + userDao);
    }

}
6.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"
       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:component-scan base-package="com.sunxiansheng.myspring.component"/>

</beans>
7.测试

CleanShot 2024-08-04 at 14.09.09@2x

8.配置UserController.java为多例的,然后测试

CleanShot 2024-08-04 at 14.11.14@2x

CleanShot 2024-08-04 at 14.11.24@2x

9.UserService调用add方法,然后测试

CleanShot 2024-08-04 at 14.13.20@2x

CleanShot 2024-08-04 at 14.13.29@2x

10.引入Bean后置处理器
1.位置

CleanShot 2024-08-04 at 14.38.08@2x

2.MyBeanPostProcessor.java
package com.sunxiansheng.myspring.process;

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * Description: Bean的后置处理器
 * @Author sun
 * @Create 2024/8/4 14:19
 * @Version 1.0
 */
@Component // 将这个类加入到容器中
public class MyBeanPostProcessor implements BeanPostProcessor {

    /**
     * 在每个Bean的初始化方法之前执行
     * @param bean
     * @param beanName
     * @return
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        // 这里可以提前对bean进行一些处理
        System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean.getClass());
        return bean;
    }

    /**
     * 在每个Bean的初始化方法之后执行
     * @param bean
     * @param beanName
     * @return
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean.getClass());
        return bean;
    }

}
3.UserService.java 设置初始化方法

CleanShot 2024-08-04 at 14.38.34@2x

4.beans.xml配置扫描

CleanShot 2024-08-04 at 14.40.15@2x

5.测试

CleanShot 2024-08-04 at 14.40.32@2x

6.注意事项
  • bean的后置处理器在初始化方法调用前后执行
  • 触发时机为单例的第一次getBean和多例的每次getBean,也就是,每个Bean都会经过Bean的后置处理器处理
11.引入AOP
1.目录

CleanShot 2024-08-04 at 15.18.09@2x

2.SmartAnimal.java
package com.sunxiansheng.myspring.aop;

/**
 * Description: SmartAnimal
 * @Author sun
 * @Create 2024/8/4 14:51
 * @Version 1.0
 */
public interface SmartAnimal {

    public float getSum(float a, float b);

    public float getSub(float a, float b);

}
3.SmartDog.java
package com.sunxiansheng.myspring.aop;

import org.springframework.stereotype.Component;

/**
 * Description: SmartDog
 * @Author sun
 * @Create 2024/8/4 14:51
 * @Version 1.0
 */
@Component // 交给Spring容器管理
public class SmartDog implements SmartAnimal {

    @Override
    public float getSum(float a, float b) {
        System.out.println("SmartDog...getSum...res=" + (a + b));
        return a + b;
    }

    @Override
    public float getSub(float a, float b) {
        System.out.println("SmartDog...getSub...res=" + (a - b));
        return a - b;
    }
}
4.SmartAnimalAspect.java
package com.sunxiansheng.myspring.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * Description: 切面类
 * @Author sun
 * @Create 2024/8/4 14:53
 * @Version 1.0
 */
@Component // 交给Spring容器管理
@Aspect // 标注这是一个切面类
public class SmartAnimalAspect {

    /**
     * @param joinPoint 保存了要切入的方法的信息
     * @Before 前置通知
     * execution(。。。) 切入表达式,表明要切入的方法,格式:格式:访问修饰符+返回类型 全类名 方法名(参数类型)
     */
    @Before(value = "execution(public float com.sunxiansheng.myspring.aop.SmartDog.getSub(float, float))")
    public void before(JoinPoint joinPoint) {
        // 获取方法签名
        Signature signature = joinPoint.getSignature();
        System.out.println("方法执行开始-日志-方法名-" + signature.getName()
                + "-参数" + Arrays.asList(joinPoint.getArgs()));
        // 还可以获取目标对象,这样就可以反射进行任何操作了
        SmartDog target = (SmartDog) joinPoint.getTarget();
        System.out.println("目标对象-" + target.getClass());
    }

    /**
     * @param joinPoint 保存了要切入的方法的信息
     * @AfterReturning 返回通知
     */
    @AfterReturning(value = "execution(public float com.sunxiansheng.myspring.aop.SmartDog.getSub(float, float))")
    public void afterReturning(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        System.out.println("方法执行正常结束-日志-方法名-" + signature.getName());
    }

    /**
     * @param joinPoint
     * @AfterThrowing 异常通知
     */
    @AfterThrowing(value = "execution(public float com.sunxiansheng.myspring.aop.SmartDog.getSub(float, float))")
    public void throwing(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        System.out.println("方法出现异常-日志-方法名-" + signature.getName());
    }

    /**
     * @param joinPoint
     * @After 后置通知
     */
    @After(value = "execution(public float com.sunxiansheng.myspring.aop.SmartDog.getSub(float, float))")
    public void after(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        System.out.println("方法最终执行完毕-日志-方法名-" + signature.getName());
    }

    /**
     * 环绕通知
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("execution(public float com.sunxiansheng.myspring.aop.SmartDog.getSub(float, float))")
    public Object logMethodExecution(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        // 获取方法信息
        String methodName = signature.getMethod().getName();
        String className = signature.getDeclaringType().getSimpleName();

        System.out.println("环绕通知 method " + className + "." + methodName);

        // 获取目标对象
        Object targetObject = joinPoint.getTarget();
        // 环绕通知获取目标对象
        System.out.println("环绕通知获取目标对象:" + targetObject);

        try {
            // 前置通知:环绕通知获取参数
            System.out.println("环绕通知获取参数:" + Arrays.asList(joinPoint.getArgs()));
            Object result = joinPoint.proceed();  // 执行目标方法
            // 返回通知:环绕通知获取结果
            System.out.println("环绕通知获取结果:" + result);
            return result;
        } catch (Exception e) {
            // 异常通知
            throw e;
        } finally {
            // 最终通知
            System.out.println("环绕通知 method " + className + "." + methodName);
        }
    }

}
5.beans.xml开启aop注解并扫描aop包

CleanShot 2024-08-04 at 15.19.30@2x

6.AppMain.java 测试AOP

CleanShot 2024-08-04 at 15.19.55@2x

CleanShot 2024-08-04 at 15.27.37@2x

6.简单分析AOP和后置处理器的关系

CleanShot 2024-08-04 at 15.41.14@2x

3.抛出问题

1.bean是怎么注入容器的?
2.为什么加了@Autowired就能被依赖注入?
3.单例多例是怎么实现的?
4.Bean的后置处理器是怎么实现的?
5.原生Spring的AOP是如何实现的?

4.将代码放到远程仓库

1.VCS -》 share

CleanShot 2024-08-04 at 14.44.28@2x

2.查看仓库

CleanShot 2024-08-04 at 14.45.31@2x

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

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

相关文章

教程3_单元层次结构1

单元层次结构是指通过将多个单元嵌套使用&#xff0c;形成具有层次结构的设计。每个单元可以包含其他单元的实例&#xff0c;这些实例称为“子单元”&#xff0c;而包含这些子单元的单元称为“父单元”。这种结构使得复杂设计变得模块化和可复用。 1、创建并使用单元实例 创建…

解读电子看板如何助力线缆行业目视化改革

线缆行业作为国民经济的重要组成部分&#xff0c;其生产过程复杂&#xff0c;环节众多&#xff0c;对生产效率和质量控制有着严格的要求。传统的管理方式往往难以满足现代化生产的需求&#xff0c;而电子看板的引入&#xff0c;为线缆行业带来了全新的管理理念和模式&#xff0…

23.合并K个升序链表-----力扣

一、题目&#xff1a; 给你一个链表数组&#xff0c;每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中&#xff0c;返回合并后的链表。 题目链接 二、示例&#xff1a; 输入&#xff1a;lists [[1,4,5],[1,3,4],[2,6]] 输出&#xff1a;[1,1,2,3,4,4,5,6] 解释…

​元宇宙虚拟展厅如何搭建?制作​线上虚拟展厅的成本

电子商务热潮的日益普及&#xff0c;让更多企业开始寻找具有创新性的方式来向客户展示他们的产品和服务。而元宇宙中的虚拟展厅也为企业提供了一个独特的机会&#xff0c;作为帮助企业展示其产品和服务特色的平台&#xff0c;元宇宙越发地受欢迎。不过在元宇宙中制作虚拟展厅的…

自带灭火电池?深蓝SL03托底事故揭秘

近日&#xff0c;网络上的一段热传视频&#xff0c;让不少网友看得先是惊心动魄&#xff0c;然后却又啧啧称奇。 该视频显示&#xff0c;8月18日晚上19点28分&#xff0c;一辆深蓝SL03在行驶中意外遭遇严重托底事故&#xff0c;车辆瞬间腾空跳跃&#xff0c;紧接着底盘出现明火…

【状态模式】设计模式系列:理解与实践(详细解读)

文章目录 状态模式详解&#xff1a;理解与实践1. 引言2. 状态模式简介2.1 定义2.2 应用场景2.3 与其他模式的关系 3. 状态模式的基本概念3.1 上下文(Context)类的角色3.2 状态(State)接口/抽象类3.3 具体状态(Concrete State)类3.4 UML类图和时序图 4. 状态模式的工作原理4.1 如…

用Python解决预测问题_多元线性回归模板

多元线性回归是一种统计学方法&#xff0c;用于分析两个或多个自变量&#xff08;解释变量&#xff09;与一个因变量&#xff08;响应变量&#xff09;之间的关系。在最简单的线性回归模型中&#xff0c;只有一个自变量和一个因变量&#xff0c;它们之间的关系可以用一条直线来…

Java对象的内存结构

文章目录 概述1. 对象头 (Header)Mark Word1. 32位HotSpot虚拟机中的MarkWord2. 64位HotSpot虚拟机中的MarkWord Class PointerArray Length指针压缩原理指针压缩测试 2. 实例数据 (Instance Data)3. 填充数据 (Padding Data) 查看 Java 对象的内存结构使用反射和VisualVM、JCo…

linux下的oracle启动命令

一、服务器断电后&#xff0c;手工启动oracle数据库步骤如下&#xff1a; 1、进入数据库服务器&#xff0c;切换到oracle用户,命令&#xff1a;su - oracle 2、启动数据库&#xff0c;命令&#xff1a; 1&#xff09; sqlplus / as sysdba 2) startup 3&#xff09;如果数据库已…

Rabbit mq 虚拟机stop无法重启

之前从后台进去&#xff0c;这个地方死活无法重启 然后重启docker 以及mq都不行 docker exec -it <CONTAINER_ID_OR_NAME> /bin/bash rabbitmqctl stop_app rabbitmqctl start_app 最后删除虚拟机&#xff0c;然后重建就行了 rabbitmqctl delete_vhost / rabbitmqctl…

C++ | Leetcode C++题解之第365题水壶问题

题目&#xff1a; 题解&#xff1a; class Solution { public:bool canMeasureWater(int x, int y, int z) {if (x y < z) {return false;}if (x 0 || y 0) {return z 0 || x y z;}return z % gcd(x, y) 0;} };

iPhone设备使用技巧:忘记密码的情况下如何解除iOS 18/17屏幕时间

我们给了儿子一部新手机。在尝试擦除旧手机上的所有内容并恢复出厂设置时&#xff0c;它要求提供 4 位屏幕时间密码。我已经尝试了我们会使用的所有可能性&#xff0c;但无法弄清楚。我们如何绕过这个问题或将手机恢复出厂设置以便我们可以出售它&#xff1f; Apple 社区 对于…

小琳AI课堂:Langchain

大家好&#xff0c;这里是小琳AI课堂&#xff0c;今天我们要探索一个令人兴奋的AI新概念——Langchain。 想象一下&#xff0c;如果我们可以把强大的大型语言模型&#xff0c;比如GPT-3&#xff0c;像乐高积木一样组合起来&#xff0c;会怎么样&#xff1f;这就是Langchain的核…

自定义开屏启动广告页

自定义开屏启动广告页 文章目录 自定义开屏启动广告页效果图简单版轮播方式css 效果图 简单版 图片 倒计时 <template><view class"guide fcc" :style"{ background: url(${ imgUrl }) no-repeat}"><view class"skip_btn" cli…

矢泽妮可二次元html视频动态引导页源码

源码介绍 矢泽妮可二次元html视频动态引导页源码 源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 效果预览 源码下载 矢泽妮可二次…

Linux系统下的容器安全:深入解析与最佳实践

在云计算和微服务架构的推动下&#xff0c;容器技术因其高效、可移植和灵活的特点&#xff0c;已经成为现代软件开发和部署的首选方案。然而&#xff0c;容器的广泛应用也带来了新的安全挑战&#xff0c;尤其是在Linux系统下&#xff0c;容器安全的实现和维护变得尤为重要。本文…

了解芯片的四大主流架构

四大主流芯片架构&#xff0c;犹如科技领域的四大支柱&#xff0c;各自矗立于技术创新的巅峰。这四大架构——X86、ARM、RISC-V与MIPS&#xff0c;不仅是芯片设计的基石&#xff0c;更是推动信息技术进步的强大动力。 一、芯片架构是什么&#xff1f; 芯片架构是指对芯片的类…

C++ 设计模式——外观模式

外观模式 C 设计模式——外观模式主要组成部分1. 外观类&#xff08;Facade&#xff09;2. 子系统类&#xff08;Subsystem&#xff09;3. 客户端&#xff08;Client&#xff09; 例一&#xff1a;工作流程示例1. 外观类&#xff08;Facade&#xff09;2. 子系统类&#xff08;…

GPU池化技术在油气勘探开发中的应用

01 背景介绍 国内某研究院为实现石油勘探开发专业软件资源的统一管理、统一监控、统一共享和统一计量&#xff0c;自主研发了勘探云管理平台(EPCP)和科研工作业务协同平台。该研究院通过两个平台实现了数十种专业勘探开发软件的共享&#xff0c;种类包括地震资料处理和解释&am…

中国四向穿梭车各角色、各玩家:大盘点

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》人俱乐部 四向穿梭车作为现代物流自动化的关键设备&#xff0c;正在全球范围内迅速发展。 本文将对四向穿梭车的不同类别的厂商进行大盘点&#x…