手写模拟spring底层原理(手写springboot)

  本篇文章为你整理了手写模拟spring底层原理(手写springboot)的详细内容,包含有spring框架 手写springboot 手写spring框架源码 手写模拟app 手写模拟spring底层原理,希望能帮助你了解 手写模拟spring底层原理。

  

// 创建一个Spring容器

 

   AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

   UserService userService = (UserService) applicationContext.getBean("userService");

   userService.test();

  

 

  项目基本结构

  1.创建@ComponentScan注解,定义包扫描路劲

  

//定义扫描路劲

 

  @Retention(RetentionPolicy.RUNTIME)

  @Target(ElementType.TYPE)

  public @interface ComponentScan {

   String value() default "";

  

 

  2.创建@Component注解,向spring容器注册bean

  

@Retention(RetentionPolicy.RUNTIME)

 

  @Target(ElementType.TYPE)

  public @interface Component {

   String value() default "";

  

 

  3.创建AppConfig配置类,定义包扫描路径。

  

//配置类

 

  @ComponentScan("com.test.service")

  public class AppConfig {

  

 

  4.创建OrderService和UserService类。

  

@Component("userService")

 

  @Scope("prototype")

  public class UserService {

   public void test(){

   System.out.println("useService");

  
//存储BeanDefinition对象

   private Map String,BeanDefinition beanDefinitionMap=new HashMap ();

   //单例池map,存储单例bean对象

   Map String,Object singletonObject=new HashMap ();

   public TestApplicationContext(Class configClass) {

   this.configClass = configClass;

   public Object getBean(String name){

   return null;

  

 

  6.从容器获取bean对象。

  

public class Test {

 

   public static void main(String[] args) {

   //创建conext容器,创建单例bean,Appconfig构造方法中完成

   TestApplicationContext applicationContext = new TestApplicationContext(AppConfig.class);

   UserService userService = (UserService) applicationContext.getBean("UserService");

  

 

  至此大体框架已经完成,接下来完成如何扫描,创建bean对象,bean初始化前,初始化,初始化后的相关实现等等

  在TestApplicationContext 的构造方法中扫描AppConfig定义的扫描路径,扫描定义的bean。

  

public TestApplicationContext(Class configClass) {

 

   this.configClass = configClass;

   //扫描

   scan(configClass);

  private void scan(Class configClass) {

   //判断当前类上是否有ComponentScan注解

   if (configClass.isAnnotationPresent(ComponentScan.class)){

   ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);

   String path = componentScanAnnotation.value();

   path=path.replace(".","/"); // com/test/service

   //获取target包下的class文件取出,解析注解,通过Appclassloader类加载器获取

   ClassLoader classLoader = TestApplicationContext.class.getClassLoader();

   URL resource = classLoader.getResource(path);

   File file = new File(resource.getFile());

   //取出目录下的文件,遍历

   if (file.isDirectory()){

   for (File f : file.listFiles()) {

   String absolutePath = f.getAbsolutePath();

   //path(C:\Users\cchuang4\IdeaProjects\springDemo\target\classes\com\test\service\OrderService.class)转换成com.test.service

   absolutePath=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));

   absolutePath=absolutePath.replace("\\",".");

   try {

   //判断class文件是否有@Component注解

   //将class文件加载进来成为class对象

   Class ? clazz = classLoader.loadClass(absolutePath);

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

   //获取beanname

   Component componentAnnotation = clazz.getAnnotation(Component.class);

   String beanName = componentAnnotation.value();

   //创建BeanDefinition对象

   BeanDefinition beanDefinition = new BeanDefinition();

   beanDefinition.setType(clazz);

   //Bean是否为单例或原型

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

   Scope scopeAnnotation = clazz.getAnnotation(Scope.class);

   String value = scopeAnnotation.value();

   beanDefinition.setScope(value);

   }else {

   //单例

   beanDefinition.setScope("singleton");

   //将bean的相关元信息存入beandefinitionMap

   beanDefinitionMap.put(beanName,beanDefinition);

   } catch (ClassNotFoundException e) {

   throw new RuntimeException(e);

  

 

  在TestApplicationContext容器加载的时候,如何去获取bean的一些元信息等,需要定义对一个bean元信息的描述,比如bean的class,bean的作用域,bean的Order等信息,在Spring生成bean的时候需要依赖于BeanDefinfition。

  创建BeanDefinfition

  

package com.spring;

 

  public class BeanDefinition {

   //类型

   private Class type;

   //作用域

   private String scope;

   //是否懒加载

   private boolean isLazy;

   public Class getType() {

   return type;

   public void setType(Class type) {

   this.type = type;

   public String getScope() {

   return scope;

   public void setScope(String scope) {

   this.scope = scope;

   public boolean isLazy() {

   return isLazy;

   public void setLazy(boolean lazy) {

   isLazy = lazy;

  

 

  单例bean的获取去遍历beanDefinitionMap,找出所有的单例bean,并存入单例池map中,在getBean()时呢能够快速的获取单例bean。TestApplicationContext的构造方法:

  

public TestApplicationContext(Class configClass) {

 

   this.configClass = configClass;

   //扫描

   scan(configClass);

   //遍历map

   for (Map.Entry String, BeanDefinition entry : beanDefinitionMap.entrySet()) {

   String beanName= entry.getKey();

   BeanDefinition beanDefinition = entry.getValue();

   if (beanDefinition.getScope().equals("singleton")){

   //获取单例bean

   Object bean = createBean(beanName, beanDefinition);

   //将单例bean存进单例池的map中,在getBean()时直接拿取

   singletonObject.put(beanName,bean);

  

 

  通过getBean()方法去获取bean,先通过beanDefinitionMap获取beanDefinition,再去判断是单例/原型bean,如果是单例bean,直接从单例池singletonObject中获取。

  

public Object getBean(String beanName){

 

   //判断是否有这个bean

   if (!beanDefinitionMap.containsKey(beanName)){

   throw new NullPointerException();

   }else {

   //获取beanDefinition对象

   BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);

   //判断单例/原型bean

   if (beanDefinition.getScope().equals("singleton")){

   //从单例池中直接获取

   Object singletonBean = singletonObject.get(beanName);

   return singletonBean;

   }else {

   //原型

   Object prototypeBean = createBean(beanName, beanDefinition);

   return prototypeBean;

  

 

  createBean()方法,创建bean对象

  

Object createBean(String beanName,BeanDefinition beanDefinition){

 

   Class clazz = beanDefinition.getType();

   Object instance = null;

   try {

   instance = clazz.getConstructor().newInstance();

   } 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);

   return instance;

  

 

  至此已经支持单例bean和原型bean的获取。

  !!!测试运行Test类

  1.当userService的@Scope("singleton")时:

  1.当userService的@Scope("prototype")时:

  此时@Component注解上要指定beanName,否则会NPE,如何获取默认的bean的名字?

  

//设置默认beanName

 

   if (beanName.equals("")){

   beanName= Introspector.decapitalize(clazz.getSimpleName());

  

 

  @AutoWire依赖注入的实现

  创建Autowired注解,并在Userservice里添加OrderService属性。

  

@Retention(RetentionPolicy.RUNTIME)

 

  @Target(ElementType.FIELD)

  public @interface Autowired {

   String value() default "";

  

 

  UserService.class

  

@Component("userService")

 

  @Scope("prototype")

  public class UserService {

   @Autowired

   private OrderService orderService;

   public void test(){

   System.out.println(orderService);

  

 

  在创建bean时进行依赖注入,先根据type,再根据name去容器中找。createBean():

  

Object createBean(String beanName,BeanDefinition beanDefinition){

 

   Class clazz = beanDefinition.getType();

   Object instance = null;

   try {

   instance = clazz.getConstructor().newInstance();

   //依赖注入

   for (Field field : clazz.getDeclaredFields()) {

   if (field.isAnnotationPresent(Autowired.class)){

   field.setAccessible(true);

   //根据type去单例池或beanDefinitionMap中去找

   //...省略

   //根据beanName去找

   field.set(instance,getBean(beanName));

   } 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);

   return instance;

  

 

  此时若先扫描到UserService,然后去创建UserService这个bean,然后在上面依赖注入的field.set(instance,getBean(beanName))时,此时OrderService单例池中还没有创建这个bean,依赖注入就会出问题。此时在创建bean时再去判断bean是否存在,不存在则再生成。

  

 public Object getBean(String beanName){

 

   //判断是否有这个bean

   if (!beanDefinitionMap.containsKey(beanName)){

   throw new NullPointerException();

   }else {

   //获取beanDefinition对象

   BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);

   //判断单例/原型bean

   if (beanDefinition.getScope().equals("singleton")){

   //从单例池中直接获取

   Object singletonBean = singletonObject.get(beanName);

   //若此时对应的bean还没有创建,如在依赖注入时

   if (singletonBean==null){

   singletonBean=createBean(beanName,beanDefinition);

   singletonObject.put(beanName,singletonBean);

   return singletonBean;

   }else {

   //原型

   Object prototypeBean = createBean(beanName, beanDefinition);

   return prototypeBean;

  

 

  测试,输出UserService里的OrderService对象:

  此时依赖注入已经完成

  初始化(InitializingBean接口)

  创建InitializingBean接口

  

public interface InitializingBean{

 

   void afterPropertiesSet() throws Exception;

  

 

  UserService.class

  

@Component("userService")

 

  @Scope("prototype")

  public class UserService implements InitializingBean {

   @Autowired

   private OrderService orderService;

   public void test(){

   System.out.println(orderService);

   @Override

   public void afterPropertiesSet() throws Exception {

   System.out.println("afterPropertiesSet");

  

 

  此时在UserService加载时afterPropertiesSet不能自动调到。

  在createBean()之后判断当前实例是否实现了InitializingBean 接口,实现了则调用afterPropertiesSet方法。

  

//调用实现了InitializingBean的afterPropertiesSet方法

 

  if (instance instanceof InitializingBean){

   ((InitializingBean)instance).afterPropertiesSet();

  

 

  BeanPostProcessor的实现

  
该接口也叫后置处理器,作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化完毕后及依赖注入完成后触发的。

  
default Object postProcessBeforeInitialization(Object bean, String beanName){

   return bean;

   default Object postProcessAfterInitialization(Object bean, String beanName){

   return bean;

  

 

 

  创建自己的类,去实现BeanPostProcessor接口,在类上加上@Component(自定义注解),以便被spring托管扫描到。在包扫描(scan()方法)时,会判断如果当前类上有@Component注解,然后会判断是否实现了BeanPostProcessor注解,

  
此时的bean的后置处理器会针对所有bean,若想针对其中一个bean,则需自己写处理逻辑。

  

@Component

 

  public class TestBeanPostProcessor implements BeanPostProcessor {

   @Override

   public Object postProcessAfterInitialization(Object bean, String beanName) {

   System.out.println(beanName);

   return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);

  

 

  创建在扫描时扫描到的那些实现了BeanPostProcessor接口的对象的list集合。

  

 //存放BeanPostProcessor对象

 

   List BeanPostProcessor beanPostProcessorList=new ArrayList ();

  

 

  在scan时判断扫描到的那些bean是否实现了BeanPostProcessor接口,实现了则加入list集合中。

  

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

 

   //判断类是否实现了BeanPostProcessor接口

   if (BeanPostProcessor.class.isAssignableFrom(clazz)){

   //获得BeanPostProcessor的实例

   BeanPostProcessor instance = (BeanPostProcessor) clazz.getConstructor().newInstance();

   //将BeanPostProcessor对象存入list(LinkList)

   beanPostProcessorList.add(instance);

   ......

  

 

  在createBean()时,在调用了实现InitializingBean的afterPropertiesSet()方法之后,再去调用BeanPostProcessor接口的方法。

  

 //调用初始化后方法

 

   for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {

   instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);

  

 

   此时BeanPostProcessor 的postProcessAfterInitialization方法返回值再次赋值给instance对象,基于这一原理可以实现AOP功能,在postProcessAfterInitialization方法里去实现一些切面的逻辑,以及可以在bean初始化前,初始化后去做一些其他的事情,如自定义注解给字段设置默认值等等。

  以上就是手写模拟spring底层原理(手写springboot)的详细内容,想要了解更多 手写模拟spring底层原理的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: