讲一讲Spring Ioc的底层原理 并手写一套
时间: 2024-05-11 16:13:51 浏览: 116
简单谈谈Spring Ioc原理解析
Spring Ioc的底层原理是基于反射和依赖注入实现的。在Spring容器启动时,会扫描所有的类,找到其中被注解为@Component、@Service、@Controller、@Repository等的类,并将其实例化为Bean对象,同时将其放入Bean工厂中进行管理。在Bean实例化的过程中,Spring使用反射机制调用构造方法或工厂方法来创建对象,并通过setter或构造方法注入依赖的其他Bean对象。这样,通过Ioc容器的管理,实现了对象之间的解耦和灵活性。
手写一套简单的Spring Ioc框架:
1. 定义注解@ComponentScan用于扫描指定包下的所有类,将被注解为@Component、@Service、@Controller、@Repository等的类实例化为Bean对象,并将其放入Bean工厂中进行管理。
```java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {
String[] basePackages();
}
```
2. 定义注解@Component用于标注需要实例化为Bean对象的类。
```java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
String value() default "";
}
```
3. 定义Bean工厂类,存储所有的Bean对象。
```java
public class BeanFactory {
private Map<String, Object> beans = new ConcurrentHashMap<>();
public Object getBean(String name) {
return beans.get(name);
}
public void addBean(String name, Object bean) {
beans.put(name, bean);
}
}
```
4. 定义Bean扫描器,扫描指定包下的所有类,并将被注解为@Component、@Service、@Controller、@Repository等的类实例化为Bean对象,并将其放入Bean工厂中进行管理。
```java
public class BeanScanner {
private BeanFactory beanFactory;
public BeanScanner(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
public void scan(String... basePackages) {
for (String basePackage : basePackages) {
String path = basePackage.replaceAll("\\.", "/");
File file = new File(this.getClass().getResource("/" + path).getFile());
if (!file.exists()) {
continue;
}
if (file.isDirectory()) {
for (File subFile : file.listFiles()) {
scan(basePackage + "." + subFile.getName().replaceAll(".class", ""));
}
} else {
String className = basePackage + "." + file.getName().replaceAll(".class", "");
try {
Class<?> clazz = Class.forName(className);
if (clazz.isAnnotationPresent(Component.class)) {
Object bean = clazz.getDeclaredConstructor().newInstance();
beanFactory.addBean(clazz.getName(), bean);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
```
5. 定义注解@Autowired用于依赖注入。
```java
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}
```
6. 定义Bean注入器,通过反射机制注入依赖的Bean对象。
```java
public class BeanInjector {
private BeanFactory beanFactory;
public BeanInjector(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
public void inject() {
for (Object bean : beanFactory.beans.values()) {
Field[] fields = bean.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Autowired.class)) {
try {
field.setAccessible(true);
Object dependencyBean = beanFactory.getBean(field.getType().getName());
field.set(bean, dependencyBean);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
}
```
7. 定义Spring Ioc框架的入口类,启动容器,并扫描指定包下的所有类,实例化为Bean对象,并将其放入Bean工厂中进行管理,最后注入依赖的Bean对象。
```java
public class SpringIoc {
public static void run(Class<?> clazz, String[] args) {
BeanFactory beanFactory = new BeanFactory();
BeanScanner beanScanner = new BeanScanner(beanFactory);
ComponentScan componentScan = clazz.getDeclaredAnnotation(ComponentScan.class);
beanScanner.scan(componentScan.basePackages());
BeanInjector beanInjector = new BeanInjector(beanFactory);
beanInjector.inject();
}
}
```
使用示例:
1. 定义两个类,一个依赖另一个。
```java
@Component
public class UserService {
public void sayHello() {
System.out.println("Hello, World!");
}
}
@Component
public class UserController {
@Autowired
private UserService userService;
public void hello() {
userService.sayHello();
}
}
```
2. 定义启动类,指定需要扫描的包,启动Spring Ioc容器。
```java
@ComponentScan(basePackages = "com.example")
public class Application {
public static void main(String[] args) {
SpringIoc.run(Application.class, args);
UserController userController = (UserController) BeanFactory.getBean("com.example.UserController");
userController.hello();
}
}
```
输出结果:
```
Hello, World!
```
阅读全文