Mini-Spring之Aware回调机制

引言

我们上一篇文章中,已经完成了一个复杂的依赖注入功能。这篇文章我们实习Spring中回调的功能,也就是一系列的Aware接口。

我们开始吧😁!

本文所有的代码都在这个项目工程里,大家需要的时候可以随时取用。传送门

我们先回顾下Aware类接口的使用,就拿最简单的一个接口BeanNameAware来说,我们自已定的类比如说上文的UserService类实现它,Spring的上下文会将beanName注入到它的属性中去,这样我们就可以拿到了这个UserService在Spring容器中的名称。

ok,具体要怎么实现呢?

首先,我们需要创建一个BeanNameAware接口,具体代码如下:

package com.zhu.spring;

public interface BeanNameAware {

    void setBeanName(String beanName);
}

然后在实现它,业务代码如下:

package com.zhu.service;

import com.zhu.spring.Autowired;
import com.zhu.spring.BeanNameAware;
import com.zhu.spring.Component;
import com.zhu.spring.Scope;

@Component
@Scope("singleton")
public class UserService implements BeanNameAware {

    @Autowired
    private OrderService orderService;

    private String beanName;

    public void test(){
        System.out.println(orderService+"|"+beanName);
    }

    @Override
    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }
}

现在的问题就是如何将值赋予给实现这个接口的累了,这一点很简单。

我们只需要在创建bean的代码中做一点点🤏小的修改,即可实现,代码如下:

Object instance = clazz.getConstructor().newInstance();

// simple dependency injection
for (Field field : clazz.getDeclaredFields()) {

  if (field.isAnnotationPresent(Autowired.class)) {
    //change true ,can assign private
    field.setAccessible(true);
    String fieldName = field.getName();
    Object bean = getBean(fieldName);
    field.set(instance, bean);
  }
}

//check bean name aware
//判断这个对象有没有实现BeanNameAware接口
if (instance instanceof BeanNameAware) {
  //实现了,就强制转换成这个接口,然后调用它的setBeanName方法
  //force cast to BeanNameAare and call its method
  ((BeanNameAware)instance).setBeanName(beanName);
}

完成之后,执行我们的测试代码,发现已经成功注入。在Spring中还有很多这样的Aware接口其实都是以类似这样的方式实现的,咋一看十分神奇,其实实现的原理很简单。