Spring底层机制环境搭建全过程

 更新时间:2024年12月09日 10:50:31   作者:S-X-S  
本文介绍了如何创建和使用Spring框架,包括模块创建、依赖引入、环境搭建、Bean的生命周期管理、AOP编程以及代码托管,通过实际操作和代码示例,详细讲解了Spring的核心概念和功能

Spring底层机制环境搭建

1.模块创建和依赖引入

聚合模块,下面有一个myspring

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

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.进行环境搭建

目录概览

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 {
}

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();
    }

}

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...");
    }

}

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);
    }

}

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>

测试

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

UserService调用add方法,然后测试

引入Bean后置处理器

1.位置

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 设置初始化方法

4.beans.xml配置扫描

5.测试

6.注意事项

  • bean的后置处理器在初始化方法调用前后执行
  • 触发时机为单例的第一次getBean和多例的每次getBean,也就是,每个Bean都会经过Bean的后置处理器处理

引入AOP

1.目录

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包

6.AppMain.java 测试AOP

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

3.抛出问题

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

4.将代码放到远程仓库

  • VCS -》 share

  • 查看仓库

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 细数Java接口的概念、分类及与抽象类的区别

    细数Java接口的概念、分类及与抽象类的区别

    下面小编就为大家带来一篇细数Java接口的概念、分类及与抽象类的区别。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-11-11
  • 如何使用jakarta.json进行json序列化和反序列化

    如何使用jakarta.json进行json序列化和反序列化

    java里,json框架何其多,常见的有jackson、fastjson、gson等,本文重点介绍如何使用jakarta.json进行json序列化和反序列化,需要的朋友可以参考下,
    2024-07-07
  • Java微信公众号推送模版消息的步骤示例详解

    Java微信公众号推送模版消息的步骤示例详解

    模板消息是一种向用户发送通知的服务,广泛用于订单状态更新、服务提醒等场景,下面,我将详细介绍如何使用Java结合微信官方提供的API来实现模板消息的推送,感兴趣的朋友跟随小编一起看看吧
    2024-08-08
  • Mybatis使用JSONObject接收数据库查询的方法

    Mybatis使用JSONObject接收数据库查询的方法

    这篇文章主要介绍了Mybatis使用JSONObject接收数据库查询,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-12-12
  • SpringBoot实现过滤器拦截器的耗时对比

    SpringBoot实现过滤器拦截器的耗时对比

    这篇文章主要为大家详细介绍了SpringBoot实现过滤器拦截器的输出接口耗时对比,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2022-06-06
  • Spring Cloud Hystrix 服务容错保护的原理实现

    Spring Cloud Hystrix 服务容错保护的原理实现

    这篇文章主要介绍了Spring Cloud Hystrix 服务容错保护的原理实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-05-05
  • Java将Date日期类型字段转换成json字符串的方法

    Java将Date日期类型字段转换成json字符串的方法

    这篇文章主要给大家介绍了关于Java将Date日期类型字段转换成json字符串的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • java编程实现求质数与因式分解代码分享

    java编程实现求质数与因式分解代码分享

    这篇文章主要介绍了Java编程实现求质数与因式分解代码分享,对二者的概念作了简单介绍(多此一举,哈哈),都是小学数学老师的任务,然后分享了求解质数和因式分解的Java代码,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • 深入理解Java中@Accessors和@Builder

    深入理解Java中@Accessors和@Builder

    本文主要介绍了@Accessors和@Builder使用,区别与坑,对使用这两个注解的有一定的帮助,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • Spring集成MyBatis 及Aop分页的实现代码

    Spring集成MyBatis 及Aop分页的实现代码

    这篇文章主要介绍了Spring集成MyBatis 及Aop分页的实现,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04

最新评论