Bootstrap

手写模拟一个简单的Spring(下)

0、上集回顾

手写模拟一个简单的Spring(上)
手写模拟一个简单的Spring(中)

4、手写中阶功能-- 依赖注入

简单的bean创建已经写好了,但是我们实际使用的Spring可不是单个bean独立使用的。接下来我们就来实现一个 @Autowired 功能

4.1、定义注解

这里我们仿造Spring,定义一个@Autowired注解。我们去掉里面的方法,就使用空注解就行,当成一个标记来使用。这个注解是在属性上使用的。
请添加图片描述

4.2、实现依赖注入

接下来开始实现依赖注入功能。

请添加图片描述
依赖注入失败!! 哈哈,我们还得处理对应的逻辑才行

依赖注入的时机是发生在bean创建的时候,所以我们这里得改造doCreateBean方法了。

改造前:
请添加图片描述
开始改造,我们首先得拿到要注入的属性才行,然后获得bean,使用反射进行属性注入填充。
请添加图片描述
效果查看,可以看到我们已经拿到对应的bean了。
请添加图片描述

5、手写高阶功能-- AOP

这里我们来挑战下,自己写个AOP的实现。在Spring中AOP是通过BeanPostProcessor来实现的,我们也仿造着来做

5.1、定义接口 BeanPostProcessor,编写方法

请添加图片描述

实现接口,AOP的功能是在bean初始化后执行的,所以这里重写了postProcessAfterInitialization方法

@Component
public class YearAopProcessor implements BeanPostProcessor {
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        // 因为每个bean的生命周期都会经过这个方法,所以这里如果想对单个bean进行处理得做判断
        if (beanName.equals("orderService")) {
            // 如果是orderService,我们进行动态代理操作
            // 这里我们选择使用JDK的动态代理,得基于接口来实现
            Object proxyInstance = Proxy.newProxyInstance(YearAopProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    // 执行代理逻辑
                    System.out.println("我执行了代理逻辑");
                    // 然后再执行被代理目标类的方法
                    return method.invoke(bean, args);
                }
            });
            return proxyInstance;
        }
        // 没有做任何处理
        return bean;
    }
}

5.2、调用方法

现在运行肯定是没有任何效果的,毕竟我们的方法都没有地方被调用。那么怎么样才能让方法被调用呢?或者说我们怎么样才能拿到我们自己写的BeanPostProcessor的实现类?

这里得在扫描的逻辑里面进行处理,把扫描到的后置处理器先缓存起来。

请添加图片描述

直接在创建bean的过程中完成调用。
请添加图片描述

效果演示。这里可以看到缓存进单例池的对象是代理对象,调用对应方法也进入了代理逻辑。
请添加图片描述

6、完结撒花🌹

简单的功能模拟就写的这儿了,我会把源码地址附上
源码传送门

;