Spring底层机制环境搭建全过程
作者: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

- 查看仓库

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