学习总结录 学习总结录
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
  • 案例实践

  • 工具使用

  • 项目搭建

  • 服务治理

  • ORM框架

  • MiniSpring

    • Spring IoC-原始Ioc
    • Spring IoC-扩展Bean
    • Spring IoC-属性注入
    • Spring Ioc-解决循环依赖
    • Spring Ioc-注解支持
      • 一、注解支持
        • 1、Spring中的注解
        • 2、支持注解
        • 3、抽象工厂类
        • 4、AutowireCapableBeanFactory
        • 5、XML上下文代码修改
      • 二、案例测试
        • 1、XML配置
        • 2、Bean类
        • 3、测试代码
      • 三、总结
      • 参考
    • Spinrg IoC-IoC完善
  • 案例归档
  • MiniSpring
旭日
2023-05-09
目录

Spring Ioc-注解支持

# 一、注解支持

# 1、Spring中的注解

在日常开发中,通常我们采用注解方式来进行Bean的注入,例如如下代码:

public class SysLogController {

    @Autowired
    private SysLogServiceImpl sysLogService;
}

这样的好处在于,不再需要在XML配置文件中进行使用ref属性,极大地增加了开发效率。

# 2、支持注解

现在我们手写的框架需要支持注解,就需要Bean的某个阶段去解释注解。

Bean的整个过程,其实我们可以简单将其分为:

  • 实例化前
  • 实例化中
  • 实例化后

这三个阶段,我们要给程序提供一个入口,来方便我们进行相应的操作,可以考虑调用一个Bean处理器Processor,由处理器来解释注解。

public interface BeanPostProcessor {


    /**
     * Bean初始化之前
     *
     * @param bean     Bean
     * @param beanName Bean id
     */
    Object postProcessBeforeInitialization(Object bean, String beanName);


    /**
     * Bean初始化之后
     *
     * @param bean     Bean
     * @param beanName Bean id
     */
    Object postProcessAfterInitialization(Object bean, String beanName);

}

接下来我们来定义注解:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}

现在我们需要利用反射来获取所有标注了Autowired 注解的成员变量,把它初始化成一个 Bean,然后注入属性。现在我们来实现BeanPostProcessor接口:

public class AutowiredAnnotationBeanPostProcessor implements BeanPostProcessor {

    private AutowireCapableBeanFactory beanFactory;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        Object result = bean;
        Class<?> clazz = bean.getClass();
        Field[] fields = clazz.getDeclaredFields();
        if (fields != null) {
            for (Field field : fields) {
                boolean isAutowired = field.isAnnotationPresent(me.xu.spring.beans.factory.annotation.Autowired.class);
                if (isAutowired) {
                    String fieldName = field.getName();
                    try {
                        Object autowiredObj = this.getBeanFactory().getBean(fieldName);
                        field.setAccessible(true);
                        field.set(bean, autowiredObj);
                    } catch (BeansException e) {
                        throw new RuntimeException(e);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
        return result;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        return null;
    }

    public AutowireCapableBeanFactory getBeanFactory() {
        return beanFactory;
    }

    public void setBeanFactory(AutowireCapableBeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }
}

这段代码核心思想:就是判断每一个属性是不是带有 Autowired 注解,如果有,就根据属性名获取 Bean。

# 3、抽象工厂类

在上段代码中,我们引入了AutowireCapableBeanFactory,这个工厂是专门处理注解的工厂,之前的SimpleBeanFactory是专门处理加载Bean逻辑的,现在我们需要为这些工厂抽象出一个抽象类工厂,去实现一些默认的功能:

public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory, BeanDefinitionRegistry {


    private Map<String, BeanDefinition> beanDefinitions = new ConcurrentHashMap<>(256);

    private List<String> beanDefinitionNames = new ArrayList<>();

    /**
     * Bean半成品
     */
    private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

    public AbstractBeanFactory() {

    }

    public void refresh() {
        for (String beanName : beanDefinitionNames) {
            try {
                getBean(beanName);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public Object getBean(String beanName) throws BeansException {
        // 先尝试直接单例获取
        Object singleton = getSingleton(beanName);
        // 如果没有,开始实例化Bean
        if (singleton == null) {
            // 尝试从Bean半成品中获取
            singleton = earlySingletonObjects.get(beanName);
            if (singleton == null) {
                // 如果半成品也没有,创建Bean实例并注册
                // 获取Bean定义
                BeanDefinition beanDefinition = beanDefinitions.get(beanName);
                try {
                    // 反射实例化Bean
                    singleton = createBean(beanDefinition);
                    // 注册单例Bean
                    registerSingleton(beanName, singleton);
                    // Bean处理器
                    //step 1 : 初始化之前
                    applyBeanPostProcessorsBeforeInitialization(singleton, beanName);
                    //step 2 : 初始化中
                    if (beanDefinition.getInitMethodName() != null && !beanDefinition.getInitMethodName().equals("")) {
                        invokeInitMethod(beanDefinition, singleton);
                    }
                    //step 3 : 初始化后
                    applyBeanPostProcessorsAfterInitialization(singleton, beanName);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return singleton;
    }

    private void invokeInitMethod(BeanDefinition beanDefinition, Object singleton) {
        Class<?> clz = singleton.getClass();
        Method method = null;
        try {
            method = clz.getMethod(beanDefinition.getInitMethodName());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        try {
            method.invoke(singleton);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    private Object createBean(BeanDefinition beanDefinition) {
        // 类名
        Class<?> clz = null;
        // 创建半成品Bean
        Object obj = doCreateBean(beanDefinition);
        // 放入半成品Bean集合中
        earlySingletonObjects.put(beanDefinition.getId(), obj);
        try {
            // 反射获取类名
            clz = Class.forName(beanDefinition.getClassName());
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 处理配置参数(属性注入)
        handleProperty(beanDefinition, clz, obj);
        return obj;
    }

    private Object doCreateBean(BeanDefinition beanDefinition) {
        Class clz = null;
        Object obj = null;
        Constructor constructor = null;

        try {
            clz = Class.forName(beanDefinition.getClassName());
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        // 处理构造器参数
        ConstructorArgumentValues constructorArgumentValues = beanDefinition.getConstructorArgumentValues();
        if (!constructorArgumentValues.isEmpty()) {
            // 参数类型
            Class<?>[] paramTypes = new Class<?>[constructorArgumentValues.getArgumentCount()];
            // 参数值
            Object[] paramValues = new Object[constructorArgumentValues.getArgumentCount()];
            // 遍历构造器参数集合
            for (int i = 0; i < constructorArgumentValues.getArgumentCount(); i++) {
                ConstructorArgumentValue constructorArgumentValue = constructorArgumentValues.getIndexedArgumentValue(i);
                if ("String".equals(constructorArgumentValue.getType()) || "java.lang.String".equals(constructorArgumentValue.getType())) {
                    paramTypes[i] = String.class;
                    paramValues[i] = constructorArgumentValue.getValue();
                } else if ("Integer".equals(constructorArgumentValue.getType()) || "java.lang.Integer".equals(constructorArgumentValue.getType())) {
                    paramTypes[i] = Integer.class;
                    paramValues[i] = Integer.valueOf((String) constructorArgumentValue.getValue());
                } else if ("int".equals(constructorArgumentValue.getType())) {
                    paramTypes[i] = int.class;
                    paramValues[i] = Integer.valueOf((String) constructorArgumentValue.getValue()).intValue();
                } else {
                    paramTypes[i] = String.class;
                    paramValues[i] = constructorArgumentValue.getValue();
                }
            }
            try {
                // 获取构造函数
                constructor = clz.getConstructor(paramTypes);
                // 利用构造函数反射实例化Bean
                obj = constructor.newInstance(paramValues);
            } catch (NoSuchMethodException | InvocationTargetException | IllegalArgumentException | SecurityException e) {
                e.printStackTrace();
            } catch (InstantiationException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        } else {
            try {
                obj = clz.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
        return obj;
    }

    private void handleProperty(BeanDefinition beanDefinition, Class<?> clz, Object obj) {
        // 处理属性
        PropertyValues propertyValues = beanDefinition.getPropertyValues();
        if (!propertyValues.isEmpty()) {
            // 遍历属性集合
            for (int i = 0; i < propertyValues.size(); i++) {
                PropertyValue propertyValue = propertyValues.getPropertyValueList().get(i);
                String pName = propertyValue.getName();
                String pType = propertyValue.getType();
                Object pValue = propertyValue.getValue();
                boolean isRef = propertyValue.isRef();

                Class<?>[] paramTypes = new Class<?>[1];
                Object[] paramValues = new Object[1];

                // 如果是基本类型
                if (!isRef) {
                    // 参数类型处理
                    if ("String".equals(pType) || "java.lang.String".equals(pType)) {
                        paramTypes[0] = String.class;
                    } else if ("Integer".equals(pType) || "java.lang.Integer".equals(pType)) {
                        paramTypes[0] = Integer.class;
                    } else if ("int".equals(pType)) {
                        paramTypes[0] = int.class;
                    } else {
                        paramTypes[0] = String.class;
                    }
                    // 参数具体数值
                    paramValues[0] = pValue;
                } else {
                    // 如果是引用类型
                    try {
                        paramTypes[0] = Class.forName(pType);
                        // 再次调用getBean方法
                        paramValues[0] = getBean((String)pValue);
                    } catch (ClassNotFoundException | BeansException e) {
                        throw new RuntimeException(e);
                    }
                }

                // 方法名字
                String methodName = "set" + pName.substring(0, 1).toUpperCase() + pName.substring(1);

                Method method = null;
                try {
                    // 获取到方法
                    method = clz.getMethod(methodName, paramTypes);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (SecurityException e) {
                    e.printStackTrace();
                }
                try {
                    // 反射调用方法
                    method.invoke(obj, paramValues);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }

            }
        }
    }


    @Override
    public Boolean containsBean(String name) {
        return containsSingleton(name);
    }

    @Override
    public void registerBean(String beanName, Object obj) {
        registerSingleton(beanName, obj);
    }

    @Override
    public boolean isSingleton(String name) {
        return beanDefinitions.get(name).isSingleton();
    }

    @Override
    public boolean isPrototype(String name) {
        return beanDefinitions.get(name).isPrototype();
    }

    @Override
    public Class getType(String name) {
        return beanDefinitions.get(name).getClass();
    }

    @Override
    public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {
        beanDefinitions.put(name, beanDefinition);
        beanDefinitionNames.add(name);
        if (!beanDefinition.isLazyInit()) {
            try {
                getBean(name);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void removeBeanDefinition(String name) {
        beanDefinitions.remove(name);
        beanDefinitionNames.remove(name);
        removeSingleton(name);
    }

    @Override
    public BeanDefinition getBeanDefinition(String name) {
        return beanDefinitions.get(name);
    }

    @Override
    public boolean containsBeanDefinition(String name) {
        return beanDefinitions.containsKey(name);
    }

    abstract public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException;

    abstract public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException;


}

我们把之前的方法比如getBean、createBean、doCreateBean方法都抽象在这个类中,其中getBean方法中有如下核心代码:

                    //step 1 : 初始化之前
                    applyBeanPostProcessorsBeforeInitialization(singleton, beanName);
                    //step 2 : 初始化中
                    if (beanDefinition.getInitMethodName() != null && !beanDefinition.getInitMethodName().equals("")) {
                        invokeInitMethod(beanDefinition, singleton);
                    }
                    //step 3 : 初始化后
                    applyBeanPostProcessorsAfterInitialization(singleton, beanName);

我们为这三个阶段提供了入口,定义了抽象方法 applyBeanPostProcessorBeforeInitialization 与 applyBeanPostProcessorAfterInitialization,由名字可以看出,分别是在 Bean 处理类初始化之前和之后执行的方法。这两个方法交给具体的继承类去实现。

# 4、AutowireCapableBeanFactory

在实现了抽象类工厂之后,我们就需要实现注解处理工厂类,让其继承抽象工厂类:

public class AutowireCapableBeanFactory extends AbstractBeanFactory{

    private final List<AutowiredAnnotationBeanPostProcessor> beanPostProcessorList = new ArrayList<>();

    public void addBeanPostProcessor(AutowiredAnnotationBeanPostProcessor beanPostProcessor) {
        beanPostProcessorList.remove(beanPostProcessor);
        beanPostProcessorList.add(beanPostProcessor);
    }
    public int getBeanPostProcessorCount() {
        return beanPostProcessorList.size();
    }
    public List<AutowiredAnnotationBeanPostProcessor> getBeanPostProcessors() {
        return beanPostProcessorList;
    }

    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;
        for (AutowiredAnnotationBeanPostProcessor beanPostProcessor : getBeanPostProcessors()) {
            beanPostProcessor.setBeanFactory(this);
            result = beanPostProcessor.postProcessBeforeInitialization(result, beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;
        for (AutowiredAnnotationBeanPostProcessor beanPostProcessor : getBeanPostProcessors()) {
            beanPostProcessor.setBeanFactory(this);
            result = beanPostProcessor.postProcessBeforeInitialization(result, beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }
}

该类中,首先使用了一个集合来存储Bean处理器,并提供对该集合一些简单的数据操作方法。

其次,实现了两个具体方法,思想也很简单,遍历Bean处理器集合,执行Bean处理器处理Bean的逻辑。

# 5、XML上下文代码修改

现在我们需要把ClassPathXmlApplicationContext中的工厂对象修改成新的工厂对象:

public class ClassPathXmlApplicationContext implements BeanFactory {
    
     AutowireCapableBeanFactory beanFactory;
    
     public ClassPathXmlApplicationContext(String fileName, boolean isRefresh) {
        // 获取资源
        Resource resource = new ClassPathXmlResource(fileName);
        // 解析资源
        //SimpleBeanFactory beanFactory = new SimpleBeanFactory();
        // 创建处理注解的工厂对象
        AutowireCapableBeanFactory beanFactory = new AutowireCapableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        reader.loadBeanDefinitions(resource);
        this.beanFactory = beanFactory;
        if (!isRefresh) {
            try {
                refresh();
            } catch (BeansException e) {
                throw new RuntimeException(e);
            }
        }
    }
    
    public void refresh() throws BeansException, IllegalStateException {
        // 注册处理器
        registerBeanPostProcessors(this.beanFactory);

        // 初始化Bean容器
        onRefresh();
    }

    private void onRefresh() {
        this.beanFactory.refresh();
    }
}

在新的refresh方法中,会先进行处理器的注册,这样BeanFactory中就有了Bena处理器,接着会调用onRefresh()方法,这个方法会去执行抽象工厂类的refresh方法。

# 二、案例测试

# 1、XML配置

<?xml version="1.0" encoding="UTF-8" ?>
    <bean id = "CService" class="me.xu.spring.test.demo03.CServiceImpl"/>
    <bean id = "FService" class="me.xu.spring.test.demo03.FServiceImpl"/>
</beans>

# 2、Bean类

public interface CService {
    void C();
}

public class CServiceImpl implements CService{

    @Override
    public void C() {
        System.out.println("子服务方法");
    }
}

public interface FService {

    void F();

    void useC();
}


public class FServiceImpl implements FService{

    @Autowired
    private CService CService;

    @Override
    public void F() {
        System.out.println("父服务方法");
    }
    @Override
    public void useC() {
        CService.C();
    }
}

# 3、测试代码

public class Demo {
    public static void main(String[] args) throws BeansException {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("demo.xml");
        FService fService = (FService)classPathXmlApplicationContext.getBean("FService");
        fService.F();
        fService.useC();

    }
}

// output
// 父服务方法
// 子服务方法

# 三、总结

通过这节的代码,我们使用了注解去加载我们所需要的Bean,流程如下:

  • 抽象工厂在加载Bean之前,会去注册一个Bean处理器
  • 加载Bean的时候,预留三个入口,分别是Bena实例化之前、Bean实例化中、Bean实例化之后
  • 在Bean实例化之前,遍历Bean处理器集合,执行处理器逻辑
  • 处理器逻辑很简单,获取Bean所自定义的字段,判断字段上是否有对应的注解,如果有注解,则获取字段名称,根据名称从BeanFactoy中获取Bean对象,然后设置该字段可访问以及该字段所对于的Bean

# 参考

手把手带你写一个 MiniSpring (opens new window)

#Spring
上次更新: 2024/06/29, 15:13:44
Spring Ioc-解决循环依赖
Spinrg IoC-IoC完善

← Spring Ioc-解决循环依赖 Spinrg IoC-IoC完善→

最近更新
01
基础概念
10-31
02
Pytorch
10-30
03
Numpy
10-30
更多文章>
Theme by Vdoing | Copyright © 2021-2024 旭日 | 蜀ICP备2021000788号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式