【Spring系列】- 手写模拟Spring框架( 四 )

创建bean利用反射机制,通过无参构造方法去获取实例,这里就是bean对象实例了 。就可以直接返回 。
// 创建beanprivate Object createBean(String beanName, BeanDefinition definition) { // 利用反射获取实例,采用无参构造方法 Class clazz = definition.getType(); // 通过无参构造方法获取实例 try {Object instance = clazz.getConstructor().newInstance(); // 到这里直接返回,bean的对象也就创建完成return instance; } catch (InstantiationException e) {e.printStackTrace(); } return null;}在构造方法扫描后要根据生成的beanDefinitionMap去创建单例bean对象 。
// 2 创建单例bean对象for (String beanName : beanDefinitionMap.keySet()) {    BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);    if (beanDefinition.getScope().equals("singleton")) { // 那么,如何保证单例呢?就需要有个单例池,singletonObjects        Object bean = createBean(beanName, beanDefinition);        singletonObjects.put(beanName, bean); // 将单例bean存到单例池中    }}运行public class Test {    public static void main(String[] args) {        LydApplicationContext applicationContext = new LydApplicationContext(AppConfig.class);        System.out.println(applicationContext.getBean("userService"));        System.out.println(applicationContext.getBean("userService"));        System.out.println(applicationContext.getBean("userService"));        System.out.println(applicationContext.getBean("userService"));        System.out.println(applicationContext.getBean("userService"));    }}我们可以先使用单例模式进行测试,我们不加scope注解,并且获取多个bean,可以看到得到的bean对象是同一个 。

【Spring系列】- 手写模拟Spring框架

文章插图
多例的时候在scope标上值,就可以看到每次获取的bean对象都是不一样的 。
【Spring系列】- 手写模拟Spring框架

文章插图
Autowired自动依赖注入当我们在UserService中使用RoleService,我们就需要通过Autowired注解进行依赖注入 。就是需要在createBean方法中,在创建实例之后,获取类中的字段,进行依赖注入,要通过判断Autowried注解 。通过字段的set方法,将bean对象注入,而这个对象如何获得呢?那就是用过getBean()方法 。
// 3 依赖注入for (Field field : clazz.getDeclaredFields()) {    // 判断字段上是否存在Autowried注解    if (field.isAnnotationPresent(Autowired.class)) {        /**         * 值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查 。         * 值为 false 则指示反射的对象应该实施 Java 语言访问检查;         * 实际上setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问 ;         */        field.setAccessible(true); // 反射需要设置这个,不然无法赋值        // 用其属性名,这就意味着private RoleService roleService;roleService不能乱取        field.set(instance, getBean(field.getName()));    }}

经验总结扩展阅读