Spring源码简易手写实现(学习过程记录)(三)

3.1依赖注入实现

创建一个OrderService类

package com.rainwood.liming.service;

import com.rainwood.spring.Component;

@Component("orderService")
public class OrderService {

}

在UserService中依赖OrderService

package com.rainwood.liming.service;

import com.rainwood.spring.Autowired;
import com.rainwood.spring.Component;
import com.rainwood.spring.Scope;

@Component("userService")
//@Scope("prototype")
public class UserService {
    @Autowired
    private OrderService orderService;

    public void test() {
        System.out.println(orderService);
    }
}

添加@Autowired注解

package com.rainwood.spring;

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

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

作用域是ElementType.METHOD, ElementType.FIELD。

在createBean方法里处理依赖注入

public  Object createBean(BeanDefination beanDefination) {
    Class clazz = beanDefination.getClazz();
    try {
        //首先看getDeclaredConstructor(Class<?>... parameterTypes)
        //这个方法会返回制定参数类型的所有构造器,包括public的和非public的,当然也包括private的。
        //getDeclaredConstructors()的返回结果就没有参数类型的过滤了。
        Object instance = clazz.getDeclaredConstructor().newInstance();

        //依赖注入
        //getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
        for (Field declaredField : clazz.getDeclaredFields()) {
            if(declaredField.isAnnotationPresent(Autowired.class)) {
                //spring在依赖注入时候会去是spring容器池里去根据类型和名字来找对应的bean
                //这里我们简化用名字来找
                Object bean = getBean(declaredField.getName());
                declaredField.setAccessible(true);//功能是启用或禁用安全检查
                declaredField.set(instance, bean);
            }
        }
        return instance;
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }
    return null;
}

3.2关于Java Field.set()

获取属性的属性值并修改属性值

public static void main(String[] args) throws NoSuchFieldException,
SecurityException,
IllegalArgumentException,
IllegalAccessException {
    Person person = new Person();
    person.setName("VipMao");
    person.setAge(24);
    person.setSex("男");
    //通过Class.getDeclaredField(String name)获取类或接口的指定属性值。  
    Field f1 = person.getClass().getDeclaredField("name");
    System.out.println("-----Class.getDeclaredField(String name)用法-------");
    System.out.println(f1.get(person));
    System.out.println("-----Class.getDeclaredFields()用法-------");
    //通过Class.getDeclaredFields()获取类或接口的指定属性值。  
    Field[] f2 = person.getClass().getDeclaredFields();
    for (Field field: f2) {
        field.setAccessible(true);
        System.out.println(field.get(person));
    }
    //修改属性值  
    System.out.println("----修改name属性------");
    f1.set(person, "Maoge");
    //修改后再遍历各属性的值  
    Field[] f3 = person.getClass().getDeclaredFields();
    for (Field fields: f3) {
        fields.setAccessible(true);
        System.out.println(fields.get(person));
    }
}

执行结果:

-----Class.getDeclaredField(String name)用法-------  
VipMao  
-----遍历属性值-------  
VipMao  
24  
男  
----修改name属性后再遍历属性值------  
Maoge  
24  
男 
posted @ 2021-10-25 16:47  rainbring  阅读(51)  评论(0)    收藏  举报