【仿写spring之ioc篇】三、检查是否实现了Aware接口并且执行对应的方法

Aware接口

Aware接口中只是设置了对应的set方法,目前只定义了三个Aware

在这里插入图片描述
以BeanNameAware为例

package com.ez4sterben.spring.ioc.factory.aware;

/**
 * bean名字清楚
 *
 * @author ez4sterben
 * @date 2023/08/31
 */
public interface BeanNameAware {

    /**
     * 设置beanName
     * @param beanName
     */
    void setBeanName(String beanName);
}

检查Aware接口

	/**
     * @param aware
     * @param clazz
     * @return boolean
     */
    public boolean isImplAware(Class<?> aware, Class<?> clazz){
        Class<?>[] interfaces = clazz.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            if (anInterface.equals(aware)) {
                return true;
            }
        }
        return false;
    }

通过invoke执行实现方法

	/**
     * beanNameAware
     * @param bean
     * @throws Exception
     */
    public void doBeanNameAware(Object bean) throws Exception {
        Class<?> aClass = bean.getClass();
        String beanName = parseBeanName(bean);
        Method setBeanName = aClass.getMethod("setBeanName", String.class);
        setBeanName.invoke(bean, beanName);
    }

    /**
     * 解析beanName
     * @param bean
     * @return {@link String}
     */
    public String parseBeanName(Object bean){
        Class<?> aClass = bean.getClass();
        Component annotation = aClass.getAnnotation(Component.class);
        String value = annotation.value();
        if ("".equals(value)){
            String name = aClass.getSimpleName();
            String s = name.substring(0, 1).toLowerCase();
            value = s + name.substring(1);
        }
        return value;
    }

    /**
     * beanFactoryAware
     * @param beanFactory
     * @param bean
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    public void doBeanFactoryAware(BeanFactory beanFactory, Object bean) throws Exception {
        Class<?> aClass = bean.getClass();
        Method setBeanName = aClass.getMethod("setBeanFactory", BeanFactory.class);
        setBeanName.invoke(bean, beanFactory);
    }

    /**
     * applicationContextAware
     * @param beanFactory
     * @param bean
     * @throws Exception
     */
    public void doApplicationContextAware(BeanFactory beanFactory, Object bean) throws Exception {
        Class<?> aClass = bean.getClass();
        Method setBeanName = aClass.getMethod("setApplicationContext", ApplicationContext.class);
        setBeanName.invoke(bean, new ApplicationContext(beanFactory));
    }

ApplicationContext是如何设计的

因为父类BeanFactory中的beanMap是私有的,为了保持一致,我们就要将对应的beanFactory对象传入构造方法然后给ApplicationContext中的beanMap赋值,由于java是值传递所以这两个对象中指向的beanMap是同一个

package com.ez4sterben.spring.ioc.context;

import com.ez4sterben.spring.ioc.factory.support.BeanFactory;

import java.util.Map;

/**
 * 应用程序上下文
 *
 * @author ez4sterben
 * @date 2023/08/30
 */
public class ApplicationContext extends BeanFactory {

    private final Map<String, Object> beanMap;

    public ApplicationContext(BeanFactory beanFactory) {
        beanMap = beanFactory.getBeanMap();
    }

    @Override
    public Map<String, Object> getBeanMap() {
        return beanMap;
    }
}

测试

为了方便测试,在BeanNameAware时向beanMap中put一下
【仿写spring之ioc篇】三、检查是否实现了Aware接口并且执行对应的方法_第1张图片
主程序中的代码

				if (beanScanner.isImplAware(BeanNameAware.class, clazz)) {
                    beanFactory.doBeanNameAware(bean);
                }
                // BeanFactoryAware
                if (beanScanner.isImplAware(BeanFactoryAware.class, clazz)) {
                    beanFactory.doBeanFactoryAware(beanFactory, bean);
                }
                // ApplicationContextAware
                if (beanScanner.isImplAware(ApplicationContextAware.class, clazz)) {
                    beanFactory.doApplicationContextAware(beanFactory, bean);
                }

测试类中的代码

/**
 * 测试组件
 *
 * @author ez4sterben
 * @date 2023/09/01
 */
@Component
@Data
public class TestComponent implements BeanNameAware, BeanFactoryAware, ApplicationContextAware {

    @Value("ez4sterben")
    private String name;

    private String age;


    @Override
    public void setBeanName(String beanName) {
        System.out.println(beanName);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        System.out.println(applicationContext.getBeanMap().toString());
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        System.out.println(beanFactory.getBeanMap().toString());
    }
}

测试结果

【仿写spring之ioc篇】三、检查是否实现了Aware接口并且执行对应的方法_第2张图片

你可能感兴趣的:(源码仿写,spring,java,后端,反射,代理,Aware)