栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

源码 - 手写精简版 Spring IOC 容器

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

源码 - 手写精简版 Spring IOC 容器

文章目录
    • 1. Spring注解开发用法
    • 2. Spring Bean的生命周期
    • 3. 手写 Spring IOC 容器
      • 1. 自定义 @Component 注解
      • 2. 自定义 @Scope 注解
      • 3. 自定义 @ComponentScan 注解
      • 4. 自定义 @Autowired 注解
      • 5. 自定义 BeanDefinition
      • 6. 自定义 InitializingBean
      • 7. 自定义 BeanPostProcessor
      • 8. 自定义 AnnotationConfigApplicationContext
      • 9. 测试
    • 4. 回顾注解和反射用法 Demo
    • 5. 回顾ClassLoader用法 Demo

1. Spring注解开发用法

① OrderDao :

package com.chahua.spring.source.dao;
import org.springframework.stereotype.Repository;

@Repository
public class OrderDao {
	public void hello(){
		System.out.println("order dao hello....");
	}
}

② 在OrderService中注入OrderDao对象:

package com.chahua.spring.source.service;
import com.chahua.spring.source.dao.OrderDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class OrderService {

	@Autowired
	private OrderDao orderDao;

	public void hello(){
		System.out.println("orderService hello....");
		orderDao.hello();
	}
}

③ 定义配置类,扫描注解所在的包:

package com.chahua.spring.source.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

// @Configuration 指定此类为Spring配置类,作为配置类,替代XML配置文件
// @ComponentScan主要就是定义扫描的路径从中找出标识了需要装配的类自动装配到spring的bean容器中
// @ComponentScan注解默认就会装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中
@Configuration
@ComponentScan("com.chahua.spring.source")
public class AppConfig {
}

④ 测试:

public class Bootstrap {
   public static void main(String[] args) {
      AnnotationConfigApplicationContext context
            = new AnnotationConfigApplicationContext(AppConfig.class);
      OrderService orderService = (OrderService)context.getBean("orderService");
      orderService.hello();
   }
}

Task :chahua-spring:Bootstrap.main()
orderService hello…
order dao hello…

2. Spring Bean的生命周期
@Service
public class OrderService implements InitializingBean {
	// 构造器
	public OrderService(){
		System.out.println("OrderService constructor.....");
	}

	@Autowired
	private OrderDao orderDao;

	public void hello(){
		System.out.println("orderService hello....");
		orderDao.hello();
	}

    // 初始化
	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("OrderService initializing.....");
	}
}
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
   // Bean的初始化前置操作
   @Override
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      if(bean instanceof OrderService){
         System.out.println("OrderService postProcessBeforeInitialization.....");
      }
      return null;
   }

   // Bean的初始化后置操作
   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      if(bean instanceof OrderService){
         System.out.println("OrderService postProcessAfterInitialization.....");
      }
      return null;
   }
}
public class Bootstrap {
   public static void main(String[] args) {
      AnnotationConfigApplicationContext context
            = new AnnotationConfigApplicationContext(AppConfig.class);
      OrderService orderService = (OrderService)context.getBean("orderService");
      orderService.hello();
   }
}

Task :chahua-spring:Bootstrap.main()
OrderService constructor…
OrderService postProcessBeforeInitialization…
OrderService initializing…
OrderService postProcessAfterInitialization…
orderService hello…
order dao hello…

3. 手写 Spring IOC 容器

1. 自定义 @Component 注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
	String value() default "";
}
2. 自定义 @Scope 注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Scope {
   String value() default "singleton";
}
3. 自定义 @ComponentScan 注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
   String value() default "";
}
4. 自定义 @Autowired 注解
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
   boolean required() default true;
}
5. 自定义 BeanDefinition
@Data
public class BeanDefinition {
   private String beanName;
   Class classType;
   String scope;
}
6. 自定义 InitializingBean
public interface InitializingBean {
   void afterPropertiesSet() throws Exception;
}
7. 自定义 BeanPostProcessor
public interface BeanPostProcessor {
   default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      return bean;
   }

   default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      return bean;
   }
}
public class BeansException extends RuntimeException{
   public BeansException(String msg) {
      super(msg);
   }

   public BeansException(String msg, Throwable cause) {
      super(msg, cause);
   }
}
8. 自定义 AnnotationConfigApplicationContext
public class AnnotationConfigApplicationContext {
   private final Class configClass;
   private Map beanDefinitionMap = new ConcurrentHashMap();
   private Map singletonObjects = new ConcurrentHashMap<>();
   private List beanPostProcessors = new ArrayList<>();

   public AnnotationConfigApplicationContext(Class configClass){
      this.configClass = configClass;
      // 1. 扫描所有的包路径,解析所有文件信息,做判断
      // 2. 注册,如果说是符合条件的bean(Component注解的类),将相关的bean信息转换为BeanDefinition
      doScan();
      // 3. 实例化,单例对象,非懒加载的Bean
      initializeNotLazyBean();
   }

   
   private void doScan() {
      if(!configClass.isAnnotationPresent(ComponentScan.class)){
         return;
      }
      ComponentScan annotation = configClass.getAnnotation(ComponentScan.class);
      // com.chahua.biz
      String packageName = annotation.value();
      // filePath: com/chahua/biz
      String filePath = packageName.replaceAll("\.", "/");
      ClassLoader classLoader = this.getClass().getClassLoader();
      // file:/D:/source_study/spring_source/spring-ioc-1/target/classes/com/chahua/biz
      URL resource = classLoader.getResource(filePath);
      // /D:/source_study/spring_source/spring-ioc-1/target/classes/com/chahua/biz
      filePath = resource.getFile();
      File file = new File(filePath);
      if(file.isDirectory()){
         File[] files = file.listFiles();
         for (File file1 : files) {
            // 获取类路径
            // com.chahua.biz.AppConfig
            String className = packageName+"."+file1.getName().replaceAll(".class","");

            // 获取到了类的全路径,从而可以通过反射获取类上的注解
            try {
               Class aClass = Class.forName(className);
               if(aClass.isAnnotationPresent(Component.class)){
                  String beanName;
                  Component component = aClass.getAnnotation(Component.class);
                  if("".equals(component.value())){
                     // 给一个默认值
                     beanName = Introspector.decapitalize(aClass.getSimpleName());
                  }else{
                     beanName = component.value();
                  }

                  String scope = ScopeType.SINGLETON;
                  if(aClass.isAnnotationPresent(Scope.class)){
                     scope = aClass.getAnnotation(Scope.class).value();
                     // 判断是不是scope类型
                  }

                  BeanDefinition definition = new BeanDefinition();
                  definition.setClassType(aClass);
                  definition.setBeanName(beanName);
                  definition.setScope(scope);
                  beanDefinitionMap.put(beanName,definition);
                  // 判断这个aClass对象是否是BeanPostProcessor类的衍生子类
                  if(BeanPostProcessor.class.isAssignableFrom(aClass)){
                     BeanPostProcessor beanPostProcessor = (BeanPostProcessor)getBean(beanName);
                     beanPostProcessors.add(beanPostProcessor);
                  }
               }
            } catch (ClassNotFoundException e) {
               throw new RuntimeException(e);
            }
         }
      }
   }

   
   private void initializeNotLazyBean() {
      Set> entries = beanDefinitionMap.entrySet();
      for (Map.Entry entry : entries) {
         BeanDefinition beanDefinition = entry.getValue();
         String scope = beanDefinition.getScope();
         if(ScopeType.SINGLETON.equals(scope)){
            craeteBean(beanDefinition);
         }
      }
   }

   
   private Object craeteBean(BeanDefinition beanDefinition) {
      String beanName = beanDefinition.getBeanName();
      if(singletonObjects.containsKey(beanName)){
         return singletonObjects.get(beanName);
      }
      // 创建Bean
      Object bean = doCreateBean(beanDefinition);
      singletonObjects.put(beanName,bean);
      return bean;

   }

   
   private Object doCreateBean(BeanDefinition beanDefinition) {
      Object exposedObject = null;
      Class classType = beanDefinition.getClassType();
      try {
         // 实例化
         Object instance = classType.getConstructor().newInstance();
         // 属性填充
         populateBean(instance,beanDefinition);
         // 对象初始化
         exposedObject = initializing(instance, beanDefinition);
      } catch (Exception e) {
         throw new BeansException(beanDefinition.getBeanName()+":创建异常");
      }
      return exposedObject;
   }

   
   private Object initializing(Object instance, BeanDefinition beanDefinition) throws Exception {
      // 初始化前置操作
      Object rs = postProcessBeforeInitialization(instance,beanDefinition.getBeanName());
      if(rs!=null){
         return rs;
      }

      // 实际初始化过程
      if(instance instanceof InitializingBean){
         ((InitializingBean) instance).afterPropertiesSet();
      }
      // 初始化后置操作
      rs = postProcessAfterInitialization(instance,beanDefinition.getBeanName());
      if(rs!=null){
         return rs;
      }
      return instance;
   }

   
   private Object postProcessBeforeInitialization(Object instance, String beanName) {
      if(instance instanceof BeanPostProcessor){
         return instance;
      }
      for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
         Object o = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
         if(o!=null){
            return o;
         }
      }
      return null;
   }

   
   private Object postProcessAfterInitialization(Object instance, String beanName) {
      if(instance instanceof BeanPostProcessor){
         return instance;
      }
      for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
         Object o = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
         if(o!=null){
            return o;
         }
      }
      return null;
   }

   
   private void populateBean(Object instance, BeanDefinition beanDefinition) {
      Class classType = beanDefinition.getClassType();
      // 获取类中所有可访问的字段(包括私有)
      Field[] declaredFields = classType.getDeclaredFields();
      try{
         for (Field declaredField : declaredFields) {
            // 判断字段上是否有@Autowired注解
            if(declaredField.isAnnotationPresent(Autowired.class)){
               // 获取属性的类型
               String simpleName = declaredField.getType().getSimpleName();
               // 将simpleName的首字符从大写转换成小写
               String fieldBeanName = Introspector.decapitalize(simpleName);
               declaredField.setAccessible(true);
               declaredField.set(instance,getBean(fieldBeanName));
            }
         }
      }catch (Exception e){
         e.printStackTrace();
         throw new BeansException(beanDefinition.getBeanName()+":创建异常");
      }
   }

   public Object getBean(String beanName){
      if(!beanDefinitionMap.containsKey(beanName)){
         throw new BeansException("找不到这样的Bean定义....");
      }
      BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
      // 如果是单例
      if(ScopeType.SINGLETON.equals(beanDefinition.getScope())){
         return craeteBean(beanDefinition);
      }else {
         return doCreateBean(beanDefinition);
      }
   }
}

9. 测试
import com.chahua.spring.annotation.Component;

@Component
public class Orderdao {
	public void hello(){
		System.out.println("OrderDao hello .... ");
	}
}
import com.chahua.spring.annotation.Autowired;
import com.chahua.spring.annotation.Component;
import com.chahua.spring.annotation.Scope;
import com.chahua.spring.bean.InitializingBean;

@Component
@Scope("prototype")
public class OrderService implements InitializingBean {
	@Autowired
	private OrderDao orderDao;

	public void hello(){
		System.out.println("OrderService hello ... ");
		orderDao.hello();
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("OrderService afterPropertiesSet.....");
	}
}
import com.chahua.spring.annotation.Component;
import com.chahua.spring.annotation.ComponentScan;

@Component
@ComponentScan("com.chahua.biz")
public class AppConfig {

}
import com.chahua.spring.annotation.Component;
import com.chahua.spring.bean.BeanPostProcessor;
import com.chahua.spring.exception.BeansException;

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    // Bean的初始化前置操作
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof OrderService){
            System.out.println("OrderService postProcessBeforeInitialization.....");
        }
        return null;
    }

    // Bean的初始化后置操作
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof OrderService){
            System.out.println("OrderService postProcessAfterInitialization.....");
        }
        return null;
    }
}
import com.chahua.biz.config.AppConfig;
import com.chahua.biz.service.OrderService;
import com.chahua.spring.context.AnnotationConfigApplicationContext;

public class Bootstrape {
   public static void main(String[] args) {
      AnnotationConfigApplicationContext context
            = new AnnotationConfigApplicationContext(AppConfig.class);
      OrderService orderService = (OrderService) context.getBean("orderService");
      orderService.hello();
   }
}

测试结果:

OrderService postProcessBeforeInitialization…
OrderService afterPropertiesSet…
OrderService postProcessAfterInitialization…
OrderService hello …
OrderDao hello …

4. 回顾注解和反射用法 Demo
import org.springframework.stereotype.Component;

@ComponentScan("com.example.fileupload.test")
public class AppConfig {

}
public class Main {
    public static void main(String[] args) throws Exception {
        // 获取Class类对象
        Class clazz = Class.forName("com.example.fileupload.test.AppConfig");

        // 1. 判断该类上是否存在指定类型的注解,如果存在则返回true,否则返回false。
        boolean annotationPresent = clazz.isAnnotationPresent(ComponentScan.class);
        // true
        System.out.println(annotationPresent);

        // 2.获取类上指定类型的注解
        ComponentScan annotation = clazz.getAnnotation(ComponentScan.class);

        // 3.获取注解的属性值
        String[] values = annotation.value();
        for (String value : values) {
            // com.example.fileupload.test
            System.out.println(value);
        }
    }
}
5. 回顾ClassLoader用法 Demo

测试demo目录 :

public class AppConfig {

}
public class Main {
    public static void main(String[] args) throws Exception {
        ClassLoader classLoader = AppConfig.class.getClassLoader();

        URL resource = classLoader.getResource("com/example/fileupload/test");
        String filePath = resource.getFile();

        // file:/D:/code/fileupload-test/target/classes/com/example/fileupload/test
        System.out.println(resource);

        // /D:/code/fileupload-test/target/classes/com/example/fileupload/test
        System.out.println(filePath);

        File file = new File(filePath);
        if(file.isDirectory()){
            File[] files = file.listFiles();
            for (File file1 :files){
                System.out.println(file1);
                System.out.println(file1.getName());
            }
        }
    }
}

输出:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/952494.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号