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接口
这个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方法的运行影响很大。
读未提交隔离级别下,可能会读到其他事务没提交的数据;
读已提交能避免脏读,但可能出现不可重复读;
可重复读能保证在一个事务里多次读同一数据结果一样,还能在一定程度上防幻读;
串行化是最严格的,事务挨个执行,数据一致性最高,但并发性能就差了。