IOC底层的实现机制-反射

目录

往userController中自动注入userService

普通反射的方式

注解的方式-未利用到set

Spring整体脉络梳理


往userController中自动注入userService

public class UserController{
   @Autowired
    private UserService userService;
}

普通反射的方式

package com.spring;

import com.spring.controller.UserController;
import com.spring.service.UserService;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class MyTest {

    //@Test
    public void test() throws Exception {
        UserController userController = new UserController();
        Class<? extends UserController> clazz = userController.getClass();

        //创建对象
        UserService userService = new UserService();
        //获取属性值
        Field serviceField = clazz.getDeclaredField("userService");
        //因为属性值是私有的,只能通过set方法和get方法设置和获取值,所以需要先拿到属性名然后拼接成对应的方法
        String name = serviceField.getName();
        //拼接方法的名称
        name = name.substring(0,1).toUpperCase() + name.substring(1, name.length());
        String setMethodName = "set" + name;
        //通过方法注入属性的对象
        Method method = clazz.getMethod(setMethodName, UserService.class);
        //反射
        method.invoke(userController, userService);
        System.out.println(userController.getUserService());

    }
}

通过一系列的反射操作将userService属性注入至userController之中。实际以上的原生代理在实际工作中都用注解进行代替。

只要获取了一个对象的class对象,就可以为这个类做随意的编写。(属性,构造器,方法啊等等)

注解的方式-未利用到set

自己实现一个@AutoWired注解

package com.spring.annotation;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Inherited
@Documented
public @interface AutoWired {
}
package com.spring;

import com.spring.annotation.AutoWired;
import com.spring.controller.UserController;
import com.spring.service.UserService;

import java.util.stream.Stream;

public class MyTest2 {
    public static void main(String[] args) {
        UserController userController = new UserController();
        Class<? extends  UserController> clazz = userController.getClass();
        UserService userService = new UserService();

        //获取所有的属性值
        Stream.of(clazz.getDeclaredFields()).forEach(field -> {
            String name = field.getName();
            AutoWired annotation = field.getAnnotation(AutoWired.class);
            //表示当前属性上加了注解
            if(annotation != null){
                field.setAccessible(true);
                //获取属性的类型(userService对应的类型为UserService)
                Class<?> type = field.getType();
                //根据获取到的类型new一个实例对象
                try {
                    Object o = type.newInstance();
                    //把创建的对象注入至属性中
                    field.set(userController, o);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        });
        System.out.println(userController.getUserService());
    }
}

 和上面的代码对比,无拼接set方法的步骤,而是利用得到的属性类型创建了一个UserService对象再设置至属性中去,不是我们自己去创建的。没有用到和set相关的东西。

类似地@Value @Controller @Component @Service都可以作类似的实现

Spring整体脉络梳理

学习建议:一定要去看官网

beanFactory:一个接口,一定存在对应的实现类。

DefaultListableBeanFactory.java中存在很多的Map(可以认为IOC容器中就是创建了很多的Map集合)

 

IOC底层的实现机制-反射

 

上一篇:php生成唯一随机码


下一篇:设计模式:六大原则