Spring IOC容器通过控制反转和依赖注入实现对spring bean生命周期的管理;AOP通过动态代理实现面向切面编程。二者构成了Spring核心机制
1 IOC 控制反转和依赖注入
1.1 控制反转机制:
传统模式,实例对象创建是通过new的形式实现,而Spring中将对象的创建 销毁权限交给IOC容器,IOC原理是通过反射和工厂模式方式实现
1.2 依赖注入实现方式/IOC类型:
- 字段注入 @Autowired / @Resource
字段通过@Autowired注解直接注入到类的字段中。这种方式简洁但不适用于生产环境,因为它降低了可测试性(测试需要mock)和可读性
- 构造器注入 @Autowired
构造器注入是使用类的构造函数来注入依赖对象。构造器注入是生产环境推荐的注入方式,他提供了不可变性和可测试性
import org.springframework.stereotype.Component; @Component public class ServiceA { public void doSomething() { System.out.println("ServiceA is doing something."); } } @Component public class ServiceB { private final ServiceA serviceA; //不可变性就是通过final来实现的,final修饰的字段一旦经过构造器初始化后就不可以改变 public ServiceB(ServiceA serviceA) { this.serviceA = serviceA; } public void doSomethingElse() { serviceA.doSomething(); System.out.println("ServiceB is doing something else."); } }
- setter方法注入 @Autowired / @Resource
setter方法注入是通过类的setter方法注入的。并且需要在setter方法上加上@Autowired注解,告诉spring这是一个注入点。setter方法注入适用于需要动态更改依赖项的场景
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class ServiceA { public void doSomething() { System.out.println("ServiceA is doing something."); } } @Component public class ServiceB { private ServiceA serviceA; // 在 set 方法上需要添加 @Autowired 注解,告诉 Spring 这是一个注入点。 @Autowired public void setServiceA(ServiceA serviceA) { this.serviceA = serviceA; } public void doSomethingElse() { serviceA.doSomething(); System.out.println("ServiceB is doing something else."); } }
1.3 IOC容器作用:
创建对象:容器负责实例化、配置、组装应用程序中的所有对象
依赖管理:这是IOC容器核心功能,通过1.2介绍的3中依赖注入方式,通过IOC容器管理组件之间的依赖关系
生命周期管理:Spirngbean 生命周期通过IOC容器管理,包含bean实例化、属性注入、初始化、使用、销毁等步骤,不需要开发者介入
作用域管理:Spring bean支持不同作用域:Singleton 单例、Prototype 原型、Session 会话、Request请求
1.4 IOC实现原理:
IOC是通过反射和工厂模式实现的
示例代码:
public interface Fruit{ void showType(); } public class Apple implements Fruit{ @Override public void showType(){ System.out.println("This is an apple"); } } public class Orange implements Fruit{ @Override public void showType(){ System.out.println("This is an Orange"); } } //工厂+反射 public class FactoryService{ public static Fruit getInstance(String className){ return (Fruit)Class.forName(className).getDeclaredConstructor().newInstance(); } } //工厂+反射获取对象 public class Client{ Fruit apple=FactoryService.getInstance("com.test.Apple"); apple.showType(); } //传统方式获取对象 public class Traditional { public static void main(String[] args) { Fruit apple = new Apple(); Fruit orange = new Orange(); apple.showType(); orange.showType(); } }
IOC底层基本实现:将扫描的@Component等注解的类转化为为beanDefinition,将这些beanDefinition注册到BeanDefinitionRegistery中,然后在IOC工厂类中会维护一个ConcurrentHashMap,ConcurrentHash的key是beanName,value就是这些beanDefinition。通过根据输入的beanName通过反射方式创建这些bean的实例化,后续回答内容参考 https://www.cnblogs.com/enhance/p/18960012
public class AdvancedBeanFactory { private ConcurrentHashMap<String, BeanDefinition> definitions; //将所有之前阶段注册beanDefinition放到ConcurrentHashMap里,通过下边createInstance反射的方式创建对应bean实例 public Object getBean(String name) { BeanDefinition def = definitions.get(name); Object instance = createInstance(def); injectDependencies(def, instance); return initializeBean(def, instance); } // ...完整的生命周期管理 }
1.5 IOC初始化过程:
首先会创建IOC容器ApplicationContext; --容器启动
通过ResurceLoader定位配置资源(如XML、注解或Java配置) --资源定位
将上一步中配置资源转化为内部数据结构BeanDefinition --BeanDefinition载入和解析
将BeanDefinition注册到BeanDefinitionRegistery中,并保存在ConcurrentHashMap里,为bean名称,值为BeanDefinition对象 --Beandefinition注册
2 AOP:
浙公网安备 33010602011771号