Why
springMVC 通过 IOC 提供了对 bean 的管理机制,让开发人员更专注于业务逻辑,节省开发成本。
又通过 三级缓存 的方式来解决 bean 在初始化时的 循环依赖问题。
那么本来通过二级缓存就可以解决的问题,为什么需要使用三级缓存呢?
就是为了更好的一次性解决通过 AOP 实现的某些特定功能增强,所以多加了一层代理factorybean来处理需要代理的 bean。
What
springMVC 管理的 bean 通常分为两种, 原始实例对象 和 代理对象。
When
原始对象
当需要实例化的类中没有实现接口或者进行 AOP 功能增强,那么springMVC 会直接初始化这个对象,最后将该原始对象添加到 bean list里面。
代理对象
当需要实例化的类中有接口的实现 / 继承/ AOP 增强, 那么 SpringMVC 会对该对象生成代理对象,方便后期注入 / 增强, 最后将代理对象添加到 bean list里面。
Select
Spring5.x - 版本默认使用 jdk 代理模式,但是由于 jdk 代理模式只能注入到接口声明的属性变量中,所以springboot2.x 将动态代理改为 cglib 代理模式, cglib 代理模式生成的代理对象是继承于原始对象实现的,所以可以实现各种变量代理注入。
Test
env: SpringBoot2.7.0
dependencies: web / aop
// Component 声明 bean
@Component
public class IndexService {
public String index() {
return "index";
}
}
// Service 声明bean, 无接口实现
@Service
public class ProxyService {
public String index() {
return "proxy service";
}
}
// Service 声明bean, 实现接口
public interface IIndexService {
public String index();
}
@Service
public class IndexServiceImp implements IIndexService{
@Override
public String index() {
return "interface index";
}
}
// AOP 切入serviec,模拟功能增强
@Aspect
@Component
public class ServiceLogAop {
@Pointcut("@within(org.springframework.stereotype.Service)")
public void service() {}
@Around("service()")
public Object service(ProceedingJoinPoint joinPoint) throws Throwable {
String className = joinPoint.getTarget().getClass().getSimpleName();
String methodName = joinPoint.getSignature().getName();
final Object obj = joinPoint.proceed();
System.out.println("================>" + className + "/" + methodName);
return obj;
}
}
// 运行
@SpringBootApplication
@RestController
@RequestMapping("/")
public class DemoBeanApplication {
public static void main(String[] args) {
SpringApplication.run(DemoBeanApplication.class, args);
}
private IndexService indexService;
private ProxyService proxyService;
private IIndexService iIndexService;
@Autowired
public DemoBeanApplication(IndexService indexService, ProxyService proxyService, IIndexService iIndexService) {
this.indexService = indexService;
this.proxyService = proxyService;
this.iIndexService = iIndexService;
}
@GetMapping("/")
public String index() {
System.out.println("indexService=============" + indexService.getClass().getName());
System.out.println("proxyService=============" + proxyService.getClass().getName());
System.out.println("iIndexService=============" + iIndexService.getClass().getName());
return proxyService.index();
}
}
// 打印log
indexService=============com.example.demo_bean.IndexService
proxyService=============com.example.demo_bean.ProxyService$$EnhancerBySpringCGLIB$$69c7f339
iIndexService=============com.example.demo_bean.IndexServiceImp$$EnhancerBySpringCGLIB$$26d546cd
================>com.example.demo_bean.ProxyService/index