【2】Spring手写模拟-依赖注入、初始化、AOP

在这里插入图片描述

首先回顾一下我们之前的流程ApplicationContext 构造方法

  • 获取Spring配置类@ComponetScan 注解,扫描包,获取其路径及其对应的字节码文件
  • 逐个扫描字节码文件
    • 利用字节码文件获取类,查看是否包含@Componet 注解,并获取或者生成BeanName
    • 获取BeanDefinition ,包含其类和类型(单例,多例)
    • 将其信息保存在beanDefinitionMap <String beanName, Class clazz>
  • 创建单例对象保存在singletonObjects <BeanName, Object>

getBean(String beanName) 方法

  • BeanDefinition 获取类信息
  • 如果是单例,尝试在singletonObjects 获取对象
    • 如果获取到的bean为空,在creatBean() // 后续说为什么为空
    • 返回获取或者创建的对象
  • 如果是多例,直接creatBean() ,返回创建的对象

creatBean(Class clazz)

返回创建的对象

完善Component

如果Component 不包含BeanName

在扫描扫描包的时候,发现含有Component 注解的时候,查看其value值,如果为空,我们用方法将其类名首字母小写为BeanName


    try {
        Class<?> clazz = classLoader.loadClass(className);
        if(clazz.isAnnotationPresent(Component.class)){
            // 获得注解value值 beanName
            Component component = clazz.getAnnotation(Component.class);
            String beanName = component.value();

            // component未赋值
            if("".equals(beanName)){
                beanName  = Introspector.decapitalize(clazz.getSimpleName());
            }




            BeanDefinition beanDefinition=new BeanDefinition();
            beanDefinition.setType(clazz);

            if(clazz.isAnnotationPresent(Scope.class)){
                Scope scope = clazz.getAnnotation(Scope.class);
                beanDefinition.setScope(scope.value());
            } else {
                beanDefinition.setScope("singleton");
            }
            beanDefinitionMap.put(beanName, beanDefinition);




        }
    } catch (ClassNotFoundException e) {
        throw new RuntimeException(e);
    }


Autoware依赖注入

我们需要实现依赖注入, @Autoware注解,在什么时候注入依赖呢

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)  // 用在变量声明上
public @interface Autoware {
}
@Scope(value = "prototype")
@Component
public class UserService {
    @Autoware
    OrderService orderService;
    public void  test(){
        System.out.println("UserService - test");
    }

}


我们应该在创建对象的时候,扫描其FIELD是否有@Autoware注解,如果包含其注解

    private Object creatBean(String beanName, BeanDefinition beanDefinition) {
        Class clazz=beanDefinition.getType();
        try {
            // 反射获取对象
            Object instance = clazz.getConstructor().newInstance();

            // 依赖注入
            for (Field f : clazz.getDeclaredFields()) {
                if(f.isAnnotationPresent(Autoware.class)){
                    f.setAccessible(true);
                    f.set(instance, getBean(f.getName())); // 通过获取其名字获取其对象 装载上去
                }
            }

            return instance;
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }

    }/

这里就解答了为什么当时

如果获取到的bean为空,在creatBean() // 后续说为什么为空

我们是逐个创建对象,有可能当前创建的对象依赖后面的还未创建的对象

Aware回调

对于UserService 想知道自己的BeanName

创建BeanNameAware 接口,包含setBeanName(String beanName) 方法

package com.yqyang.spring;

public interface BeanNameAware {
    public void setBeanName(String beanName);
}

对于UserService 实现该接口

我们在creatBean() 时就能查看类是否instanceof 该接口,如果是可以回调UserService 实现的接口方法

    private Object creatBean(String beanName, BeanDefinition beanDefinition) {
        Class clazz=beanDefinition.getType();
        try {
            // 反射获取对象
            Object instance = clazz.getConstructor().newInstance();

            // 依赖注入
            for (Field f : clazz.getDeclaredFields()) {
                if(f.isAnnotationPresent(Autoware.class)){
                    f.setAccessible(true);
                    f.set(instance, getBean(f.getName()));
                }
            }

            // Aware回调
            if(instance instanceof BeanNameAware){
                ((BeanNameAware) instance).setBeanName(beanName);
            }



            return instance;
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }

    }

模拟Spring初始化机制

和上面差不多,定义InitializingBean 接口

package com.yqyang.spring;

public interface InitializingBean {
    public void afterPropertiesSet();
}

对于UserService 实现该接口

我们在creatBean() 时就能查看类是否instanceof 该接口,如果是可以回调UserService 实现的接口方法

    private Object creatBean(String beanName, BeanDefinition beanDefinition) {
        Class clazz=beanDefinition.getType();
        try {
            // 反射获取对象
            Object instance = clazz.getConstructor().newInstance();

            // 依赖注入
            for (Field f : clazz.getDeclaredFields()) {
                if(f.isAnnotationPresent(Autoware.class)){
                    f.setAccessible(true);
                    f.set(instance, getBean(f.getName()));
                }
            }

            // Aware回调
            if(instance instanceof BeanNameAware){
                ((BeanNameAware) instance).setBeanName(beanName);
            }

            // 初始化
            if (instance instanceof InitializingBean) {
                ((InitializingBean)instance).afterPropertiesSet();
            }



            return instance;
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }

    }

BeanPostProcessor

可能在初始化前后执行一些操作

定义BeanPostProcessor接口,返回值为Object为了后面的动态代理AOP

public interface BeanPostProcessor {
    public Object postProcessBeforeInitialization(String beanName, Object bean);
    public Object postProcessAfterInitialization(String beanName, Object bean);
}

我们需要在ApplicationContext添加变量

private ArrayList<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();

其获取是在扫描包时,获取实现该接口的对象,添加到beanPostProcessorList

try {
  Class<?> clazz = classLoader.loadClass(className);

  if (clazz.isAnnotationPresent(Component.class)) {

      if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
          BeanPostProcessor instance = (BeanPostProcessor) clazz.newInstance();
          beanPostProcessorList.add(instance);
      }

      Component component = clazz.getAnnotation(Component.class);
      String beanName = component.value();

      if (beanName.equals("")) {
          beanName = Introspector.decapitalize(clazz.getSimpleName());
      }


      BeanDefinition beanDefinition = new BeanDefinition();
      beanDefinition.setType(clazz);

      if (clazz.isAnnotationPresent(Scope.class)) {
          Scope scopeAnnotation = clazz.getAnnotation(Scope.class);
          beanDefinition.setScope(scopeAnnotation.value());
      } else {
          beanDefinition.setScope("singleton");
      }

      beanDefinitionMap.put(beanName, beanDefinition);

  }

creatBean() 初始化前后,遍历列表,获取各个对象执行方法

  • 这样如果有多个对象实现BeanPostProcessor ,也就是beanPostProcessorList 中有多个方法,创建一个对象的时候会导致各个实现该对象的方法重复执行,在实现接口的时候可以利用传入创建Bean的参数启到限制的作用,只让我们创建的对象执行。
    • beanName
    • instance
private Object createBean(String beanName, BeanDefinition beanDefinition){

        Class clazz = beanDefinition.getType();

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

            // 依赖注入
            for (Field f : clazz.getDeclaredFields()) {
                if (f.isAnnotationPresent(Autowired.class)) {
                    f.setAccessible(true);
                    f.set(instance, getBean(f.getName()));
                }
            }

            // Aware
            if (instance instanceof BeanNameAware) {
                ((BeanNameAware)instance).setBeanName(beanName);
            }

            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                instance = beanPostProcessor.postProcessBeforeInitialization(beanName, instance);
            }

            // 初始化
            if (instance instanceof InitializingBean) {
                ((InitializingBean)instance).afterPropertiesSet();
            }

            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                instance = beanPostProcessor.postProcessAfterInitialization(beanName, instance);
            }

            return instance;

        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        return null;
    }

测试类-记得放在扫描包下

@Component
public class YqyangBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(String beanName, Object bean) {
       if (beanName.equals("userService")) {
           System.out.println("1111");
       }

       return bean;
    }

    @Override
    public Object postProcessAfterInitialization(String beanName, Object bean) {

        if (beanName.equals("userService")) {
            System.out.println("2222");
        }

        return bean;
    }
}

在这里插入图片描述

AOP

jdk实现动态代理需要接口,创建接口UserInterface

public interface UserInterface {

    public void test();
}

UserService 实现该接口

@Scope
@Component
public class UserService implements UserInterface {
    @Autoware
    OrderService orderService;
    public void  test(){
        System.out.println("UserService - test");
    }
}

在实现postProcessAfterInitialization 接口时,获取其动态代理对象,并且调用原来的方法。

@Component
public class ZhouyuBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(String beanName, Object bean) {
       if (beanName.equals("userService")) {
           System.out.println("1111");
       }

       return bean;
    }

    @Override
    public Object postProcessAfterInitialization(String beanName, Object bean) {

        if (beanName.equals("userService")) {
            Object proxyInstance = Proxy.newProxyInstance(ZhouyuBeanPostProcessor.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;
    }
}

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值