【Spring系列】- 手写模拟Spring框架( 六 )


@Overridepublic Object postAfterProcessor(String beanName, Object bean) {    System.out.println("初始化后的bean:" + beanName + " -- " + bean);    if (beanName.equals("userService")) {        // 创建一个代理对象, 代理的是UserInterface这个        Object proxyInstance = Proxy.newProxyInstance(MyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {            @Override            /**             * proxy:代理对象             * method:代理对象当前正在执行的方法             */            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                System.out.println("切面逻辑");                return method.invoke(bean, args);            }        });        return proxyInstance;    }    return bean;}源码备注springLydApplicationContextpublic class LydApplicationContext {    private Class configClass; // 注入的配置类    private ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(); // key是component名字    private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>(); // 单例池    private ArrayList<BeanPostProcessor> beanPostProcessorList = new ArrayList<>(); // 记录BeanPostProcessor,在扫描的时候判断,使用    public LydApplicationContext(Class configClass) { // 构造方法        this.configClass = configClass;        // spring容器创建之后        // 1 扫描        // 通过配置文件的注解获取扫描路径        if (configClass.isAnnotationPresent(ComponentScan.class)) {            ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);            // 1.1 扫描路径:只是个包名,扫描的是java的class文件,而并非源文件 , com.lyd.service            String path = componentScanAnnotation.value();            // 1.2 将路径文件替换成/的形式            path = path.replace(".","/");            // 1.3 通过类加载器获取资源路径            ClassLoader classLoader = LydApplicationContext.class.getClassLoader();            URL resource = classLoader.getResource(path);            // 1.4 转成文件形式 , 主要是为了获取他的绝对地址            File file = new File(resource.getFile());//            System.out.println(file);            if (file.isDirectory()) { // 如果是文件夹                File[] files = file.listFiles();                for (File f : files) {                    String absolutePath = f.getAbsolutePath(); // 获取绝对路径                    System.out.println("绝对路径:" + absolutePath);                    // 1.5 对编译文件进行处理                    if (absolutePath.endsWith(".class")) { // 判断是否为编译文件                        /**                         * 需要拿到的是编译文件,通过类加载器去获取                         * 需要将com\lyd\service\UserService转成com.lyd.service.UserService                         */                        String className = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));                        className = className.replace("\\", ".");                        System.out.println("类名:" + className);                        try {                            // 1.6 通过全限定名使用类加载器获取类 (利用反射机制)                            Class<?> clazz = classLoader.loadClass(className);                            // 1.7 在通过这个clazz(类)来判断是否有component注解,有则是bean                            if (clazz.isAnnotationPresent(Component.class)) {                                // 6 判断是否是并加入beanPostProcessorList,这里不能使用instanceof                                if (BeanPostProcessor.class.isAssignableFrom(clazz)) {                                    // 直接生成对象                                    BeanPostProcessor instance = (BeanPostProcessor) clazz.newInstance();                                    // 然后保存进去                                    beanPostProcessorList.add(instance);                                }                                Component annotation = clazz.getAnnotation(Component.class);                                String beanName = annotation.value();                                // * 默认生成bean,如果只使用Component注解,没有写上beanName的值,那么就需要自动生成                                if (beanName.equals("")) {                                    // 默认开头小字母                                    beanName = Introspector.decapitalize(clazz.getSimpleName());                                }                                /**                                 * 這就是一个bean了                                 * 然而在这里并不是直接就创建bean了 , bean分为了单例bean和多例bean                                 */                                BeanDefinition beanDefinition = new BeanDefinition();                                beanDefinition.setType(clazz);                                if (clazz.isAnnotationPresent(Scope.class)) { // 判断是单例还是多例                                    Scope scope = clazz.getAnnotation(Scope.class);                                    beanDefinition.setScope(scope.value());                                } else {                                    beanDefinition.setScope("singleton");                                }                                beanDefinitionMap.put(beanName, beanDefinition);                            }                        } catch (Exception e) {                            e.printStackTrace();                        }                    }                }            }        }        // 2 创建单例bean对象        for (String beanName : beanDefinitionMap.keySet()) {            BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);            if (beanDefinition.getScope().equals("singleton")) { // 那么,如何保证单例呢?就需要有个单例池,singletonObjects                Object bean = createBean(beanName, beanDefinition);                singletonObjects.put(beanName, bean); // 将单例bean存到单例池中            }        }    }    // 创建bean    private Object createBean(String beanName, BeanDefinition definition) {        // 利用反射获取实例,采用无参构造方法        Class clazz = definition.getType();        // 通过无参构造方法获取实例        try {            Object instance = clazz.getConstructor().newInstance(); // 到这里直接返回,bean的对象也就创建完成            // 3 依赖注入            for (Field field : clazz.getDeclaredFields()) {                // 判断字段上是否存在Autowried注解                if (field.isAnnotationPresent(Autowired.class)) {                    /**                     * 值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查 。                     * 值为 false 则指示反射的对象应该实施 Java 语言访问检查;                     * 实际上setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问 ;                     */                    field.setAccessible(true); // 反射需要设置这个 , 不然无法赋值                    // 用其属性名,这就意味着private RoleService roleService;roleService不能乱取                    field.set(instance, getBean(field.getName()));                }            }            // * instanceof:是针对某个对象去判断是否实现某个类            // 4 Aware回调机制            if (instance instanceof BeanNameAware) {                ((BeanNameAware)instance).setBeanName(beanName);            }            // 6 BeanPostProcessor 初始化前 AOP 遍历beanPostProcessorList            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {                instance = beanPostProcessor.postBeforeProcessor(beanName, instance);            }            // 5 初始化            if (instance instanceof InitializingBean) {                ((InitializingBean)instance).afterPropertiesSet();            }            // 6 BeanPostProcessor 初始化后 AOP            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {                instance = beanPostProcessor.postAfterProcessor(beanName, instance);            }            return instance;        } catch (InstantiationException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        } catch (InvocationTargetException e) {            e.printStackTrace();        } catch (NoSuchMethodException e) {            e.printStackTrace();        }        return null;    }    // 获取bean对象    public Object getBean(String beanName) {        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);        if (beanDefinition == null) {            throw new NullPointerException("找不到bean名字为[" + beanName + "]的bean对象");        } else { // 找到就做相应的操作            String scope = beanDefinition.getScope();            if (scope.equals("singleton")) {                // 通过单例池获取                Object bean = singletonObjects.get(beanName);                if (bean == null) {                    // 单例池中如果没有bean,就需要去创建                    bean = createBean(beanName, beanDefinition);                    singletonObjects.put(beanName, bean);                }                return bean;            } else {                // 多例的就不需要记录,每次都是通过创建                return createBean(beanName, beanDefinition);            }        }    }}

推荐阅读