设为首页 加入收藏

TOP

day13-实现Spring底层机制-03(一)
2023-07-25 21:43:04 】 浏览:82
Tags:day13- 实现 Spring -03

实现Spring底层机制-03

7.阶段5-后置处理器的实现

7.1分析

阶段5目标:bean后置处理器的实现

7.2代码实现

新增:

image-20230129200839338

1.创建 InitializingBean 接口,实现该接口的 Bean 需要实现 Bean 的初始化方法

bean后置处理器的两个方法,调用时机分别在 Bean 初始化方法的前后。因此要实现bean后置处理器,首先要实现 Bean 的初始化方法。

image-20230129181757213

可以参考原生 Spring 规范来定义这个接口

package com.li.spring.processor;

/**
 * @author 李
 * @version 1.0
 * 说明:
 * 1.根据 spring 原生机制定义了一个接口
 * 2.该接口有一个方法 afterPropertiesSet(),
 * 3.afterPropertiesSet() 在 bean的 setter方法后执行,相当于原生的spring的 bean初始化方法
 * 4.当一个Bean实现了这个接口后,就要实现afterPropertiesSet(),即 bean的初始化方法
 */
public interface InitializingBean {
    void afterPropertiesSet() throws Exception;
}

2.为了测试,在MonsterService中实现该接口,并实现该方法,作为MonsterService的初始化方法

注:其他注解及自动装配的实现详见上一篇

package com.li.spring.component;

import com.li.spring.annotation.AutoWired;
import com.li.spring.annotation.Component;
import com.li.spring.annotation.Scope;
import com.li.spring.processor.InitializingBean;

/**
 * @author 李
 * @version 1.0
 * MonsterService 是一个 Service
 * 1.如果指定了value,那么在注入spring容器时,以你指定的为准
 * 2.如果没有指定value,则使用类名(首字母小写)作为默认名
 */
@Component//(value = "monsterService") //将 MonsterService注入到自己的spring容器中
@Scope(value = "prototype")
public class MonsterService implements InitializingBean {
    //使用自定义注解修饰属性,表示该属性通过容器完成依赖注入
    // (说明:按照名字进行组装)
    @AutoWired(required = true)
    private MonsterDao monsterDao;

    public void m1() {
        monsterDao.hi();
    }

    /**
     * 1.afterPropertiesSet()就是在bean的setter方法执行完毕之后,被spring容器调用
     * 2.即 bean的初始化方法
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("MonsterService 初始化方法被调用");
    }
}

3.修改MySpringApplicationContext.java,添加逻辑:在创建后bean实例后,判断是否需要进行初始化。

容器中常用的一个方法是,根据该类是否实现了某个接口,来判断该类是否要执行某个业务逻辑。这个接口被称为标记接口。

部分代码:

//完成createBean(BeanDefinition)方法
public Object createBean(BeanDefinition beanDefinition) {
    //得到Bean的class对象
    Class clazz = beanDefinition.getClazz();
    try {
        //反射创建bean实例
        Object instance = clazz.getDeclaredConstructor().newInstance();
        //todo 这里要加入依赖注入的业务逻辑
        //1.遍历当前要创建对象的所有属性字段
        for (Field declaredField : clazz.getDeclaredFields()) {
            //2.判断字段是否有AutoWired注解
            if (declaredField.isAnnotationPresent(AutoWired.class)) {
                //判断是否需要自动装配
                AutoWired autoWiredAnnotation =
                        declaredField.getAnnotation(AutoWired.class);
                if (autoWiredAnnotation.required()) {
                    //3.得到字段的名称
                    String name = declaredField.getName();
                    //4.通过getBean()方法获取要组装的对象
                    //如果name对应的对象时单例的,就到单例池去获取,如果是多例的,就反射创建并返回
                    Object bean = getBean(name);
                    //5.进行组装
                    //暴破
                    declaredField.setAccessible(true);
                    declaredField.set(instance, bean);
                }
            }
        }
        System.out.println("======已创建好实例=====" + instance);
        
        //todo 判断是否要执行bean的初始化方法
        // 1.判断当前创建的 bean对象是否实现了 InitializingBean
        // 2.instanceof 表示判断对象的运行类型 是不是 某个类型或某个类型的子类型
        if (instance instanceof InitializingBean) {
            //3.将instance转成接口类型,调用初始化方法
            try {
                ((InitializingBean) instance).afterPropertiesSet();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return instance;
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }
    //如果反射对象失败
    return null;
}

4.测试类

//...
public class AppMain {
    public static void main(Stri
首页 上一页 1 2 3 4 5 6 下一页 尾页 1/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇springboot~openfeign开启熔断之.. 下一篇《RPC实战与核心原理》学习笔记Da..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目