Spring

BeanFactory Interface

1
2
3
4
5
6
@SpringBootApplication
public class DemoJavaSpringApplication {
    public static void main(String[] args) {
       ConfigurableApplicationContext context= SpringApplication.run(DemoJavaSpringApplication.class, args);
    }
}

可以发现ConfigurableApplicationContext接口继承了BeanFactory接口 Alt text 这个context里面包含了一个beanFactory变量。

实现类

DefaultListableBeanFactory这个类去实现 BeanFactory。 他继承了一个类,DefaultSingletonBeanRegistry,这个类是用来注册单例的。它有一个字段singletonObjects用来存放 Bean

1
2
3
4
5
6
7
8
Field field= DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
field.setAccessible(true);
//拿到那个实际的beanFactory对象
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
Map<String, Object> map=(Map<String, Object>) field.get(beanFactory);
map.forEach((k,v)->{
    System.out.println(k);
});

spring启动之后,打印出所有bean的名字.

AOP

动态代理

将横切关注点(如日志、事务、权限校验)从核心业务逻辑中分离出来,通过动态代理实现代码的复用和解耦。

1
2
3
4
5
6
7
8
@Aspect
@Component
public class LogAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void beforeMethod(JoinPoint joinPoint) {
        System.out.println("方法执行前:" + joinPoint.getSignature().getName());
    }
}

@Aspect 用来定义切面逻辑,@PointCut用来标注切入点。

1
2
3
4
5
6
7
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethods() {}

@Before("serviceMethods()")
public void beforeServiceMethod(JoinPoint joinPoint) {
    System.out.println("Service方法执行前");
}

serviceMethods():定义了一个切入点方法,方法体为空(仅用于承载切入点表达式)。

字节码操作

像 ASM、Javassist 这样的工具,能在字节码层面修改类的行为。比如添加方法、修改方法逻辑、增加字段等。这样避免修改源码。

@Transactional

Spring 注解的事务(@Transactional)本质上是对数据库事务的一种抽象和管理,它底层依赖数据库提供的事务功能 。比如对于 MySQL 数据库,Spring 事务最终会调用 MySQL 的事务机制来实现事务控制。

不同的隔离级别对 Spring @Transactional方法的运行影响很大。

读未提交隔离级别下,可能会读到其他事务没提交的数据;

读已提交能避免脏读,但可能出现不可重复读;

可重复读能保证在一个事务里多次读同一数据结果一样,还能在一定程度上防幻读;

串行化是最严格的,事务挨个执行,数据一致性最高,但并发性能就差了。