模拟实现Spring注解

模拟实现Spring的@Autowired,@Bean,@Component注解

  • 注解

@Autowired

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {
}

@Bean

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Bean {
}

@Component

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
    String value();
}

@ComponentScan

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
    String value();
}

@Scope

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
    String value();
}
  • BeanDefinition实体
public class BeanDefinition {
	//Spring容器管理的对象的Class
    private Class clazz;
    //singleton or prototype
    private String scope;

    public BeanDefinition() {
    }

    public BeanDefinition(Class clazz, String scope) {
        this.clazz = clazz;
        this.scope = scope;
    }

    public Class getClazz() {
        return clazz;
    }

    public void setClazz(Class clazz) {
        this.clazz = clazz;
    }

    public String getScope() {
        return scope;
    }

    public void setScope(String scope) {
        this.scope = scope;
    }
}
  • ApplicationContext

属性

public class ApplicationContext {
    //配置类
    public Class configClass;
    //缓存单例的对象
    private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();
    //缓存包含Bean信息的BeanDefinition对象
    private ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
    }

构造方法

  • 扫描带有@ComponentScan和@Bean注解的配置类,生成BeanDefinition对象并缓存到beanDefinitionMap里
private void scan(Class configClass) {
   //用来保存类的全限类名
   List<String> list = new ArrayList<>();
   ClassLoader classLoader = ApplicationContext.class.getClassLoader();
   if (configClass.isAnnotationPresent(ComponentScan.class)) {
       ComponentScan componentScanAnnotation = (ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);
       //获取@ComponentScan注解里指定扫描的包名
       String path = componentScanAnnotation.value();
       //包名 例如com.jxz.annotation 替换成 com/jxz/annotation
       String realPath = path.replace(".", "/");
       URL resource = classLoader.getResource(realPath);
       File file = new File(resource.getFile());
       //递归指定包及子包里的所有以.class结尾的全限类名 保存到list里
       getClassNames(file, list);
       /*
		 private void getClassNames(File file, List<String> classNames) {
		     if (file.isDirectory()) {
		         File[] files = file.listFiles();
		         for (File f : files) {
		             if (f.isDirectory()) {
		                 getClassNames(f, classNames);
		             }
		             String fileName = f.getAbsolutePath();
		             if (fileName.endsWith(".class")) {
		                 String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
		                 className = className.replace("\\", ".");
		                 classNames.add(className);
		             }
		         }
		     }
		 }
       */
   } else {
       throw new RuntimeException("找不到指定配置信息");
   }


	 list.stream().forEach(className -> {
	      try {
	          //获取每个类的Class对象
	          Class<?> clazz = classLoader.loadClass(className);
	          //判断是否有Component注解
	          if (clazz.isAnnotationPresent(Component.class)) {
	              Component componentAnnotation = clazz.getDeclaredAnnotation(Component.class);
	              String beanName = componentAnnotation.value();
	              //创建BeanDefinition对象
	              BeanDefinition beanDefinition = new BeanDefinition();	
	             	//设置clazz属性
	              beanDefinition.setClazz(clazz);
	              //如果有@Scope注解
	              if (clazz.isAnnotationPresent(Scope.class)) {
	                  Scope scopeAnnotation = clazz.getDeclaredAnnotation(Scope.class);
	                  String scope = scopeAnnotation.value();
	                  if (!"singleton".equals(scope) && !"prototype".equals(scope)) {
	                      throw new RuntimeException("不支持的Scope类型");
	                  }
	                  beanDefinition.setScope(scope);
	              } else {
	              	//默认为单例
	                  beanDefinition.setScope("singleton");
	              }
	              //缓存
	              beanDefinitionMap.put(beanName, beanDefinition);
	          }
	      } catch (ClassNotFoundException e) {
	          e.printStackTrace();
	      }
	  });
	}
  • 缓存带有@Bean注解方法返回的对象到singletonObjects里
Method[] methods = configClass.getDeclaredMethods();
 try {
     Object o = configClass.newInstance();
     for (Method method : methods){
     	//遍历获取到的所有方法判断是否有@Bean注解
         if (method.isAnnotationPresent(Bean.class)){
             method.setAccessible(true);
             //得到return的对象
             Object instance = method.invoke(o);
             //beanName默认为方法名
             String beanName = method.getName();
             //缓存调用方法返回的对象
             singletonObjects.put(beanName, instance);
             Class<?> clazz = method.getReturnType();
             //缓存BeanDefinition对象
             BeanDefinition beanDefinition = new BeanDefinition(clazz, "singleton");
             beanDefinitionMap.put(beanName, beanDefinition);
         }
     }
 } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
     e.printStackTrace();
 }
  • 遍历beanDefinitionMap生成Scope为singleton的单例对象,缓存到singletonObject里
for (String beanName : beanDefinitionMap.keySet()) {
    BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
    if ("singleton".equals(beanDefinition.getScope())) {
        Object bean = null;
        try {
            bean = createBean(beanName, beanDefinition);
        } catch (IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }
        singletonObjects.put(beanName, bean);
    }
}
  • createBean方法
private Object createBean(String beanName, BeanDefinition beanDefinition) throws IllegalAccessException, InstantiationException {
    //如果singletonObjects中已经存在则直接返回
    //防止重复生成@Bean注解的对象或依赖的对象
    Object o = singletonObjects.get(beanName);
    if (null != o && "singleton".equals(beanDefinition.getScope())){
        return o;
    }
    
    Class clazz = beanDefinition.getClazz();
    Object instance = clazz.newInstance();
    for (Field field : clazz.getDeclaredFields()) {
    	//如果属性上有@Autowired注解
        if (field.isAnnotationPresent(Autowired.class)) {
            field.setAccessible(true);
            //以 byName注入  getBean方法判断对象scope类型并返回
            //getBean方法写到下面了
            Object bean = getBean(field.getName());
            if (bean == null) {
            	//代码进到这里说明注入的对象还没有创建或没有此类型的BeanDifinition对象
                BeanDefinition beanD = beanDefinitionMap.get(field.getName());
                //查看是否存在BeanDefinition对象
                if (null != beanD){
                	//递归调用自己优先创建要注入的对象
                    bean = createBean(field.getName(), beanD);
                    if ("singleton".equals(beanD.getScope())){
                    	//缓存到singletonObjects防止单例对象重复生成
                    	//下次走到这里会被上面的if语句ruturn掉
                        singletonObjects.put(field.getName(), bean);
                    }
                }else {
                	//没有抛异常
                    throw new RuntimeException("Can't Autowired " + field.getName());
                }
            }
            field.set(instance, bean);
        }
    }
    return instance;
}
  • getBean方法
public Object getBean(String beanName) {
    if (beanDefinitionMap.containsKey(beanName)) {
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        //如果是单例的直接从缓存里取
        if ("singleton".equals(beanDefinition.getScope())) {
            Object o = singletonObjects.get(beanName);
            return o;
        }
        //如果不是单例,使用createBean方法
        if ("prototype".equals(beanDefinition.getScope())) {
            try {
                return createBean(beanName, beanDefinition);
            } catch (IllegalAccessException | InstantiationException e) {
                e.printStackTrace();
            }
        }
    }
    return null;
}
  • 完整的ApplicationContext代码
public class ApplicationContext {

    //配置类
    public Class configClass;
    //缓存单例的对象
    private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();
    //缓存包含Bean信息的BeanDefinition对象
    private ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();


    public ApplicationContext(Class configClass) { //传入带入@ComponentScan注解的配置类
        this.configClass = configClass;

        //解析
        scan(configClass);

        //缓存带有@Bean注解的方法 beanName为方法名
        Method[] methods = configClass.getDeclaredMethods();
        try {
            Object o = configClass.newInstance();
            for (Method method : methods) {
                if (method.isAnnotationPresent(Bean.class)) {
                    method.setAccessible(true);
                    Object instance = method.invoke(o);
                    String beanName = method.getName();
                    //缓存调用方法返回的对象,beanName为方法名
                    singletonObjects.put(beanName, instance);
                    Class<?> clazz = method.getReturnType();
                    BeanDefinition beanDefinition = new BeanDefinition(clazz, "singleton");
                    beanDefinitionMap.put(beanName, beanDefinition);
                }
            }
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

        //遍历beanDefinitionMap生成单例对象并缓存
        for (String beanName : beanDefinitionMap.keySet()) {
            BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
            if ("singleton".equals(beanDefinition.getScope())) {
                Object bean = null;
                try {
                    bean = createBean(beanName, beanDefinition);
                } catch (IllegalAccessException | InstantiationException e) {
                    e.printStackTrace();
                }
                singletonObjects.put(beanName, bean);
            }
        }
    }

    //解析配置类
    private void scan(Class configClass) {
        //用来保存类的全限类名
        List<String> list = new ArrayList<>();
        //获取@Component注解里的包名
        ClassLoader classLoader = ApplicationContext.class.getClassLoader();
        if (configClass.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScanAnnotation = (ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);
            String path = componentScanAnnotation.value();
            //包名 例如com.jxz.annotation 替换成 com/jxz/annotation
            String realPath = path.replace(".", "/");
            URL resource = classLoader.getResource(realPath);
            File file = new File(resource.getFile());
            //递归获取此文件里的所有以.class结尾的全限类名 保存到list里
            getClassNames(file, list);
        } else {
            throw new RuntimeException("找不到指定配置信息");
        }


        list.stream().forEach(className -> {
            try {
                //获取每个类的Class对象
                Class<?> clazz = classLoader.loadClass(className);
                //判断是否有Component注解
                if (clazz.isAnnotationPresent(Component.class)) {
                    Component componentAnnotation = clazz.getDeclaredAnnotation(Component.class);
                    String beanName = componentAnnotation.value();
                    //先把clazz保存到BeanDefinition
                    BeanDefinition beanDefinition = new BeanDefinition();
                    beanDefinition.setClazz(clazz);
                    //如果有@Scope注解
                    if (clazz.isAnnotationPresent(Scope.class)) {
                        Scope scopeAnnotation = clazz.getDeclaredAnnotation(Scope.class);
                        String scope = scopeAnnotation.value();
                        if (!"singleton".equals(scope) && !"prototype".equals(scope)) {
                            throw new RuntimeException("不支持的Scope类型");
                        }
                        beanDefinition.setScope(scope);
                    } else {
                        beanDefinition.setScope("singleton");
                    }
                    //缓存
                    beanDefinitionMap.put(beanName, beanDefinition);
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        });
    }

    //反射创建对象
    private Object createBean(String beanName, BeanDefinition beanDefinition) throws IllegalAccessException, InstantiationException {
        //如果singletonObjects中已经存在则直接返回
        Object o = singletonObjects.get(beanName);
        if (null != o && "singleton".equals(beanDefinition.getScope())) {
            return o;
        }
        Class clazz = beanDefinition.getClazz();
        Object instance = clazz.newInstance();
        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(Autowired.class)) {
                field.setAccessible(true);
                Object bean = getBean(field.getName());
                if (bean == null) {
                    BeanDefinition beanD = beanDefinitionMap.get(field.getName());
                    if (null != beanD) {
                        bean = createBean(field.getName(), beanD);
                        if ("singleton".equals(beanD.getScope())) {
                            singletonObjects.put(field.getName(), bean);
                        }
                    } else {
                        throw new RuntimeException("Can't autowired" + field.getName());
                    }
                }
                field.set(instance, bean);
            }
        }
        return instance;
    }


    //递归获取file里所有类的全限类名
    private void getClassNames(File file, List<String> classNames) {
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File f : files) {
                if (f.isDirectory()) {
                    getClassNames(f, classNames);
                }
                String fileName = f.getAbsolutePath();
                if (fileName.endsWith(".class")) {
                    String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
                    className = className.replace("\\", ".");
                    classNames.add(className);
                }
            }
        }
    }

    //获取bean方法
    public Object getBean(String beanName) {
        if (beanDefinitionMap.containsKey(beanName)) {
            BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
            //如果是单例的直接从缓存里取
            if ("singleton".equals(beanDefinition.getScope())) {
                Object o = singletonObjects.get(beanName);
                return o;
            }
            //如果不是单例,使用createBean方法
            if ("prototype".equals(beanDefinition.getScope())) {
                try {
                    return createBean(beanName, beanDefinition);
                } catch (IllegalAccessException | InstantiationException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
}
  • 测试

AppConfig

@ComponentScan("com.jxz.spring")
public class AppConfig {

    @Bean
    public User user(){
        User user = new User();
        user.setUserName("Hello");
        user.setPassword("World");
        return user;
    }
}

User(测试@Bean注解)

public class User {
    private String userName;
    private String password;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

Student(测试是否是多例)

@Component("student")
@Scope("prototype")
public class Student {
}

UserService(测试@Component和@Autowired)

@Component("userService")
public class UserService {
    @Autowired
    public User user;
}
  • 测试类Test
public class Test {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ApplicationContext(AppConfig.class);

        User user = (User) applicationContext.getBean("user");
        System.out.println(user);

        Student student1 = (Student) applicationContext.getBean("student");
        Student student2 = (Student) applicationContext.getBean("student");
        System.out.println(student1.hashCode());
        System.out.println(student2.hashCode());

        UserService userService = (UserService) applicationContext.getBean("userService");
        System.out.println(userService);
        System.out.println(userService.user);
    }
}

测试结果

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值