引言
我们上一篇文章中,已经实现了简单类的注入功能,这篇文章主要是为了完成复杂类的注入功能。废话少说,我们开始出发。
本文所有的代码都在这个项目工程里,大家需要的时候可以随时取用。传送门
补全bean名称生成
在之前的代码中,bean的名称一直都是取@Component
注解中的值,但是这个值可以为空的,我们没有处理这个分支下的情况,这次我们就进行一个补全,具体代码如下:
Component componentAnnotation = clazz.getAnnotation(Component.class);
String beanName = componentAnnotation.value();
//只需要在原来的代码中增加一段这样的代码
if("".equals(beanName)){
//transfer name ,eg: Service->service SService->SService, SerR->serR
//这里是直接取java.beans包下的一个方法,目的是将首字母小写。
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
依赖注入
回到正题,在Spring中依赖注入需要一个注解,用它实例化需要依赖的类。因此,我们也需要创建一个注解,代码如下:
package com.zhu.spring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}
准备工作做完了,我们需要思考一下,在哪里去创建这个依赖呢?
没错,就是在创建bean的时候,我们需要创建这个依赖的bean,也就是在之前的createBean方法中去创建,具体代码如下:
private Object createBean(String beanName, BeanDefinition beanDefinition){
Class clazz = beanDefinition.getType();
try {
Object instance = clazz.getConstructor().newInstance();
// 新增的代码,查找类的所有变量,判断是否有Autowired注解修饰的类
// simple dependency injection
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Autowired.class)) {
//有Autowired修饰的类,即需要注入的类
//change true ,can assign private
field.setAccessible(true);
//获取字段的名称作为类名称
String fieldName = field.getName();
//直接调用getBean方法查询之前是否有创建过的bean,没有就新建,具体看一下实现
Object bean = getBean(fieldName);
//将bean设置进去
field.set(instance, bean);
}
}
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
我们可以做个测试,先创建一个OrderService类,然后在UserService中注入它,并打印结果,具体如下:
@Component
@Scope("singleton")
public class OrderService {
}
@Component
@Scope("singleton")
public class UserService {
@Autowired
private OrderService orderService;
public void test(){
System.out.println(orderService);
}
}
public class Test {
public static void main(String[] args) {
MiniSpringApplicationContext miniSpringApplicationContext = new MiniSpringApplicationContext(AppConfig.class);
UserService userService = (UserService)miniSpringApplicationContext.getBean("userService");
userService.test();
}
}
//打印结果:
//com.zhu.service.OrderService@610455d6
自此,我们解决了我们依赖注入的问题,可以在代码中写更加复杂的bean了。