Java手写实现IOC

什么是依赖注入?

平常的Java开发中,程序员在某个类中需要依赖其它类的方法。我们通常是new一个依赖类再调用类实例的方法set进去,这种开发存在的问题是new的类实例不好统一管理。所以Spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过Spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。

依赖注入的另一种说法是"控制反转"。通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员而控制反转是指new实例工作不由我们程序员来做而是交给Spring容器来做。
注意在这篇文章中我们用注解的方法去模拟,采用懒加载方式。
其中涉及到一个扫描包中其他Java类的扫描工具类
模拟的思路如下:
在这里插入图片描述

  • @Component注解类:用来注解需要哪些类的定义信息,被扫描生成BeanDefination,可以拥有别名。
  • @Autowired注解类:用来注解依赖类成员,表示该成员需要注入,可以根据别名注入,可以生成单例或非单例的实例;
  • @Qualifier注解类:当某个要被注入的成员是接口或者父类时,确定要注入哪个子类,ImplementationClass记录父类名称。
  • BeanDefinition:记录一个类的信息,包含三个成员:klass是类的类型,object是记录已经注入的实例,isinject表示是否已经注入,它的作用有两个,一是在getbean时不会再次依赖注入,二是巧妙解决循环依赖。
  • BeanFactory:顾名思义就是生产bean的地方了,我这里实现的比较粗糙,将扫描和依赖注入均放在这里,它有两个成员beanPool:用来存放BeanDefinition,alias用来存放别名,beanfactory会先扫描包启动容器,然后在调用getBean时进行依赖注入(这里的依赖注入实际就是用递归表达出来的)。

具体代码

  • 三个注解类:
package annotation;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(TYPE)
public @interface Component {
   
   String name() default "";
}
package annotation;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(FIELD)
public @interface Autowired {
   
   String name() default "";
   boolean isSinglton() default true;
}
package annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * 如果要向接口注入,需要确定注入接口实现类的哪一个
 * @author quan
 * @create 2020-06-25 12:52
 */

@Retention(RUNTIME)
@Target(FIELD)
public @interface Qualifier {
   
    String ImplementationClass() default "";
}
  • BeanDefinition: 类的定义,以及生成的单例也会包含在这里
package core;

/**
 * 类的定义
 */
public class BeanDefinition {
   
   private Class<?> klass;
   private Object object;
   private boolean inject;

   public BeanDefinition() {
   
   }

   protected Class<?> getKlass() {
   
      return klass;
   }
   
   protected void setKlass(Class<?> klass) {
   
      this.klass = klass;
   }
   
   protected Object getObject() {
   
      return object;
   }
   protected Object getPropertyObject() throws IllegalAccessException, InstantiationException {
   
      return klass.newInstance();
   }
   
   protected void setObject(Object object) {
   
      this.object = object;
   }

   protected boolean isInject() {
   
      return inject;
   }

   protected void setInject(boolean inject) {
   
      this.inject = inject;
   }

   @Override
   public String toString() {
   
      return "[klass=" + klass.getSimpleName(
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值