手写Spring底层机制

打印 上一主题 下一主题

主题 865|帖子 865|积分 2595

手写Spring底层机制

IOC容器
  1.     //定义 BeanDefinitionMap 存放 beanDefinition
  2.     private ConcurrentHashMap<String,BeanDefinition> beanDefinitionMap =
  3.             new ConcurrentHashMap<>();
  4.     //定义 singletonObjects 存放 单例
  5.     private ConcurrentHashMap<String,Object> singletonObjects =
  6.             new ConcurrentHashMap<>();
  7.     //定义beanPostProcessorList 存放 BeanPostProcessor
  8.     private ArrayList<BeanPostProcessor> beanPostProcessorList=
  9.             new ArrayList<>();
复制代码
构造器
  1. //构造器
  2. public ZyApplicationContext(Class configClass) {
  3.     this.configClass = configClass;
  4.     beanDefinitionsByScan();
  5.     //初始化单例池
  6.     initSingletonObjects();
  7. }
复制代码
扫描包
  1. private void beanDefinitionsByScan() {
  2.         //获得扫描的包
  3.         ComponentScan componentScan =
  4.                 (ComponentScan)this.configClass.getDeclaredAnnotation(ComponentScan.class);
  5.         //获取路径
  6.         String path = componentScan.value();
  7.         path = path.replace(".","/");
  8.         //获取工作路径
  9.         ClassLoader classLoader = ZyApplicationContext.class.getClassLoader();
  10.         URL resource = classLoader.getResource(path);
  11.         File file = new File(resource.getFile());
  12.         if (file.isDirectory()){
  13.             File[] files = file.listFiles();
  14.             for (File f : files) {
  15.                 //获取绝对路径
  16.                 String fileAbsolutePath = f.getAbsolutePath();
  17.                 if (fileAbsolutePath.endsWith(".class")) {
  18.                     //获取className
  19.                     String className = fileAbsolutePath.substring(fileAbsolutePath.lastIndexOf("\") + 1, fileAbsolutePath.indexOf(".class"));
  20.                     String fullPath = path.replace("/", ".") + "." + className;
  21.                     try {
  22.                         Class<?> clazz = classLoader.loadClass(fullPath);
  23.                         if (clazz.isAnnotationPresent(Component.class)) {
  24.                             //初始化beanPostProcessorList
  25.                             if (BeanPostProcessor.class.isAssignableFrom(clazz)){
  26.                               BeanPostProcessor beanPostProcessor =
  27.                                       (BeanPostProcessor)clazz.newInstance();
  28.                                 beanPostProcessorList.add(beanPostProcessor);
  29.                                 continue;
  30.                             }
  31.                             //处理className
  32.                             String value = clazz.getDeclaredAnnotation(Component.class).value();
  33.                             if ("".equals(value)){
  34.                                 className = StringUtils.uncapitalize(className);
  35.                             }else {
  36.                                 className = value;
  37.                             }
  38.                             System.out.println("是一个bean 类名= " + className);
  39.                             //设置 beanDefinition
  40.                             BeanDefinition beanDefinition = new BeanDefinition();
  41.                             //设置scope
  42.                             if (clazz.isAnnotationPresent(Scope.class)){
  43.                                 beanDefinition.setScope(clazz.getDeclaredAnnotation(Scope.class).value());
  44.                             }else{
  45.                                 beanDefinition.setScope("singleton");
  46.                             }
  47.                             beanDefinition.setClazz(clazz);
  48.                             //放入 beanDefinitionMap
  49.                             beanDefinitionMap.put(className,beanDefinition);
  50.                         } else {
  51.                             System.out.println("不是一个bean 类名= " + className);
  52.                         }
  53.                     } catch (Exception e) {
  54.                         throw new RuntimeException(e);
  55.                     }
  56.                 }
  57.             }
  58.         }
  59.     }
复制代码
初始化单例池
  1. private void initSingletonObjects() {
  2.         Enumeration<String> keys = beanDefinitionMap.keys();
  3.         while (keys.hasMoreElements()){
  4.             String beanName = keys.nextElement();
  5.             BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
  6.             String scope = beanDefinition.getScope();
  7.             if ("singleton".equals(scope)){
  8.                 Object bean = createBean(beanDefinition,beanName);
  9.                 singletonObjects.put(beanName,bean);
  10.             }
  11.         }
  12.     }
复制代码
getBean()
  1. public Object getBean(String name){
  2.         if (beanDefinitionMap.containsKey(name)){
  3.             BeanDefinition beanDefinition = beanDefinitionMap.get(name);
  4.             String scope = beanDefinition.getScope();
  5.             if ("singleton".equals(scope)){
  6.                 return singletonObjects.get(name);
  7.             }else{
  8.                 return createBean(beanDefinition,name);
  9.             }
  10.         }
  11.         return null;
  12.     }
复制代码
createBean()
  1. private Object createBean(BeanDefinition beanDefinition,String beanName){
  2.         try {
  3.             Class clazz = beanDefinition.getClazz();
  4.             Object instance = clazz.getDeclaredConstructor().newInstance();
  5.             
  6.             return instance;
  7.         } catch (InstantiationException e) {
  8.             throw new RuntimeException(e);
  9.         } catch (IllegalAccessException e) {
  10.             throw new RuntimeException(e);
  11.         } catch (InvocationTargetException e) {
  12.             throw new RuntimeException(e);
  13.         } catch (NoSuchMethodException e) {
  14.             throw new RuntimeException(e);
  15.         }
  16.     }
复制代码
依赖注入


  • 加入到createBean()中
  1.   private Object createBean(BeanDefinition beanDefinition,String beanName){
  2.         try {
  3.             Class clazz = beanDefinition.getClazz();
  4.             Object instance = clazz.getDeclaredConstructor().newInstance();
  5.             //依赖注入
  6.             Field[] declaredFields = clazz.getDeclaredFields();
  7.             for (Field declaredField : declaredFields) {
  8.                 if (declaredField.isAnnotationPresent(Autowired.class)){
  9.                     if (declaredField.getDeclaredAnnotation(Autowired.class).required()){
  10.                         //获的字段名
  11.                         String fieldName = declaredField.getName();
  12.                         //获取实例
  13.                         Object bean = getBean(fieldName);
  14.                         declaredField.setAccessible(true);
  15.                         declaredField.set(instance,bean);
  16.                     }
  17.                 }
  18.             }
  19.          
  20.             return instance;
  21.         } catch (InstantiationException e) {
  22.             throw new RuntimeException(e);
  23.         } catch (IllegalAccessException e) {
  24.             throw new RuntimeException(e);
  25.         } catch (InvocationTargetException e) {
  26.             throw new RuntimeException(e);
  27.         } catch (NoSuchMethodException e) {
  28.             throw new RuntimeException(e);
  29.         }
  30.     }
复制代码
后置处理器


  • 加入到createBean()中
  1.   private Object createBean(BeanDefinition beanDefinition,String beanName){
  2.         try {
  3.             Class clazz = beanDefinition.getClazz();
  4.             Object instance = clazz.getDeclaredConstructor().newInstance();
  5.             //依赖注入
  6.             Field[] declaredFields = clazz.getDeclaredFields();
  7.             for (Field declaredField : declaredFields) {
  8.                 if (declaredField.isAnnotationPresent(Autowired.class)){
  9.                     if (declaredField.getDeclaredAnnotation(Autowired.class).required()){
  10.                         //获的字段名
  11.                         String fieldName = declaredField.getName();
  12.                         //获取实例
  13.                         Object bean = getBean(fieldName);
  14.                         declaredField.setAccessible(true);
  15.                         declaredField.set(instance,bean);
  16.                     }
  17.                 }
  18.             }
  19.             //后置处理器 before()
  20.             //遍历 beanPostProcessorList
  21.             for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
  22.                 Object current = beanPostProcessor.
  23.                         postProcessBeforeInitialization(instance, beanName);
  24.                 if (current!=null){
  25.                     instance = current;
  26.                 }
  27.             }
  28.             //初始化bean
  29.             if (instance instanceof InitializingBean){
  30.                 try {
  31.                     ((InitializingBean)instance).afterPropertiesSet();
  32.                 } catch (Exception e) {
  33.                     throw new RuntimeException(e);
  34.                 }
  35.             }
  36.             //后置处理器 after()
  37.             //遍历 beanPostProcessorList
  38.             for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
  39.                 Object current = beanPostProcessor.
  40.                         postProcessAfterInitialization(instance, beanName);
  41.                 if (current!=null){
  42.                     instance = current;
  43.                 }
  44.             }
  45.             System.out.println("");
  46.             System.out.println("-------------------------------------");
  47.             System.out.println("");
  48.             return instance;
  49.         } catch (InstantiationException e) {
  50.             throw new RuntimeException(e);
  51.         } catch (IllegalAccessException e) {
  52.             throw new RuntimeException(e);
  53.         } catch (InvocationTargetException e) {
  54.             throw new RuntimeException(e);
  55.         } catch (NoSuchMethodException e) {
  56.             throw new RuntimeException(e);
  57.         }
  58.     }
复制代码
AOP


  • AOP需要在后置处理器的before方法中实现
  1. @Override
  2.     public Object postProcessAfterInitialization(Object bean, String beanName) {
  3.         System.out.println("ZyBeanPostProcessor后置处理器-After-beanName= "+beanName);
  4.         //aop实现
  5.         if("smartDog".equals(beanName)) {
  6.             Object proxyInstance = Proxy.newProxyInstance(ZyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
  7.                 @Override
  8.                 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  9.                     Object result = null;
  10.                     if ("getSum".equals(method.getName())) {
  11.                         SmartAnimalAspect.showBeginLog();
  12.                         result = method.invoke(bean, args);
  13.                         SmartAnimalAspect.showBeginLog();
  14.                     }else {
  15.                         result = method.invoke(bean, args);//执行目标方法
  16.                     }
  17.                     return result;
  18.                 }
  19.             });
  20.             return proxyInstance;
  21.         }
  22.         return bean;
  23.     }
复制代码
几个Spring的题目

1.单例/多例怎么实现的?@scope为什么可以实现?
回答:@scope 的value属性可以设置为singleton /prototype
通过getBean()方法 如果bean中的属性scope为singleton 就从单例池直接拿,如果是prototype 就调用createBean()创建一个实例
2.怎样实现依赖注入?@Autowired Spring容器怎样实现依赖注入?
回答: 遍历clazz的所有属性 通过@Autowired注解 如果有 先获取字段名 再通过getBean()获取对应的bean 末了用filed.set()方法将实例的该属性设置为 获取到的bean 实现依赖注入
3.后置处理器 为什么在创建bean 时 调用bean 的 init方法初始化前/后 调用?
  1. //后置处理器 before()
  2.             //遍历 beanPostProcessorList
  3.             for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
  4.                 Object current = beanPostProcessor.
  5.                         postProcessBeforeInitialization(instance, beanName);
  6.                 if (current!=null){
  7.                     instance = current;
  8.                 }
  9.             }
  10.             //初始化bean
  11.             if (instance instanceof InitializingBean){
  12.                 try {
  13.                     ((InitializingBean)instance).afterPropertiesSet();
  14.                 } catch (Exception e) {
  15.                     throw new RuntimeException(e);
  16.                 }
  17.             }
  18.             //后置处理器 after()
  19.             //遍历 beanPostProcessorList
  20.             for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
  21.                 Object current = beanPostProcessor.
  22.                         postProcessAfterInitialization(instance, beanName);
  23.                 if (current!=null){
  24.                     instance = current;
  25.                 }
  26.             }
复制代码
4.后置处理器和AOP有什么关系,Spring Aop怎样实现??
回答:aop的实现实在后置处理器的before中实现的,底层利用动态代理
  1. //aop实现
  2.         if("smartDog".equals(beanName)) {
  3.             Object proxyInstance = Proxy.newProxyInstance(ZyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
  4.                 @Override
  5.                 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  6.                     Object result = null;
  7.                     if ("getSum".equals(method.getName())) {
  8.                         SmartAnimalAspect.showBeginLog();
  9.                         result = method.invoke(bean, args);
  10.                         SmartAnimalAspect.showBeginLog();
  11.                     }else {
  12.                         result = method.invoke(bean, args);//执行目标方法
  13.                     }
  14.                     return result;
  15.                 }
  16.             });
  17.             return proxyInstance;
  18.         }
  19.         return bean;
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

立聪堂德州十三局店

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表