| 
 
 目录  
补充说明  
编写基础工程  
实现 ApplicationContext  
实现@ComponentScan注解  
实现@Component注解  
spring原理具体简单模拟实现  
 
补充说明 
在开始前,先补充一个bean的生成时间。在之前的spring入门使用代码里,是这么写的  
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) context.getBean("userService");
userService.test();  
生成bean,是在我们第一行代码生成的,第二行代码只是去单例池去获取这个bean而已,但是这个是对于普通加载的,如果要生成的bean,声明采用了懒加载的方式,那就不再是第一行代码生成bean了,如果是一个单例bean,我们每次去getBean,都是同一个,但是如果是一个多例bean(也称为原型bean),每次去get,都是创建新的bean  
编写基础工程 
我们来自己实现一下上面的获取bean的方式  
实现 ApplicationContext 
package own.study.spring;
public class MyApplicationContext {
    private Class config;
    public MyApplicationContext (Class config) {
        this.config = config;
    }
    public Object getBean (String beanName) {
        return null;
    }
}
  
做一个配置类  
package own.study.spring;
public class Appconfig {
}
  
做完配置类,我们还需要一个测试类  
package own.study.spring;
public class Test {
    public static void main(String[] args) {
        MyApplicationContext myApplicationContext = new MyApplicationContext(Appconfig.class);
        UserService userService = (UserService) myApplicationContext.getBean("userService");
    }
}
  
写到测试类的时候发现,还需要一个用来当做bean的类  
package own.study.spring;
public class UserService {
    public void printMessage () {
        System.out.println("this is userService's method uotput");
    }
}
  
看似我们就这么实现了,但是这么做肯定不能用,毕竟还有注解,当然,我们说了手动模拟实现,就不能用现成的spring的注解,所以我们也来实现一下注解  
实现@ComponentScan注解 
package own.study.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.TYPE)
public @interface ComponentScan {
    String value() default "";
}
  
这样,我们就可以使用我们自己的注解  
package own.study.spring;
@ComponentScan(value = "own.study.spring")
public class Appconfig {
}
  
实现@Component注解 
package own.study.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.TYPE)
public @interface Component {
    
    String value() default "";
    
}
  
package own.study.spring;
@Component(value = "userService")
public class UserService {
    public void printMessage () {
        System.out.println("this is userService's method uotput");
    }
}
  
spring原理具体简单模拟实现 
在第一行,肯定不是直接去创建bean,一定是选需要扫描的,扫描哪些是需要生成bean的  
也就是说,首先需要拿到扫描路径,我们可以从传进来的配置类上获取,判断有没有 @ComponentScan 注解  
package own.study.spring;
import java.lang.annotation.Annotation;
public class MyApplicationContext {
    private Class config;
    public MyApplicationContext (Class config) {
        this.config = config;
        if (config.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScan = (ComponentScan) config.getAnnotation(ComponentScan.class);
            String sacnPath = componentScan.value();
            System.out.println("sacnPath = " + sacnPath);
        }
    }
    public Object getBean (String beanName) {
        return null;
    }
}
  
   
可以看到,我们拿到了这个地址,自定义的扫描路径,拿到了扫描路径之后,我们就可以去对应的target目录下,拿到所有的class文件,然后解析这些class文件上有没有注解,如果仔细看过idea的启动参数信息,也能看到,是去用的target的class文件  
   
?因为这个目录是分隔符,所以我们得把路径换一下格式  
package own.study.spring;
import java.io.File;
import java.lang.annotation.Annotation;
public class MyApplicationContext {
    private Class config;
    public MyApplicationContext (Class config) {
        this.config = config;
        if (config.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScan = (ComponentScan) config.getAnnotation(ComponentScan.class);
            String sacnPath = componentScan.value();
            sacnPath = sacnPath.replace(".", "/");
            System.out.println("sacnPath = " + sacnPath);
        }
    }
    public Object getBean (String beanName) {
        return null;
    }
}
  
?   
?然后我们就可以拿到整个路径下的所有文件  
package own.study.spring;
import java.io.File;
import java.lang.annotation.Annotation;
import java.net.URL;
public class MyApplicationContext {
    private Class config;
    public MyApplicationContext (Class config) {
        this.config = config;
        if (config.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScan = (ComponentScan) config.getAnnotation(ComponentScan.class);
            String sacnPath = componentScan.value();
            sacnPath = sacnPath.replace(".", "/");
            System.out.println("sacnPath = " + sacnPath);
            ClassLoader classLoader = MyApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(sacnPath);
            File file = new File(resource.getFile());
            if (file.isDirectory()) {
                for (File tmpFile : file.listFiles()) {
                    System.out.println(tmpFile.getAbsolutePath());
                }
            }
        }
    }
    public Object getBean (String beanName) {
        return null;
    }
}
  
   
?现在我们拿到了这class文件,我们可以把这个类加载进来,然后判断是不是有注解,注意,类加载器只能加载我们之前的以 ‘.’ 为分隔符的路径,所以我们还得替换一下才行(这里因为我的包名和路径名冲突了,所以我把包名从 own 换成了 pri )  
package pri.study.spring;
import java.io.File;
import java.net.URL;
public class MyApplicationContext {
    private Class config;
    public MyApplicationContext (Class config) throws ClassNotFoundException {
        this.config = config;
        if (config.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScan = (ComponentScan) config.getAnnotation(ComponentScan.class);
            String sacnPath = componentScan.value();
            sacnPath = sacnPath.replace(".", "/");
            System.out.println("sacnPath = " + sacnPath);
            ClassLoader classLoader = MyApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(sacnPath);
            File file = new File(resource.getFile());
            if (file.isDirectory()) {
                for (File tmpFile : file.listFiles()) {
                    System.out.println(tmpFile.getAbsolutePath());
                    String absolutePath = tmpFile.getAbsolutePath();
                    absolutePath = absolutePath.substring(absolutePath.indexOf("pri"), absolutePath.indexOf(".class")).replace("\\", ".");
                    System.out.println("absolutePath = " + absolutePath);
                    Class<?> aClass = classLoader.loadClass(absolutePath);
                    System.out.println(aClass.isAnnotationPresent(Component.class));
                }
            }
        }
    }
    public Object getBean (String beanName) {
        return null;
    }
}
  
?   
?看,我们拿到了有注解的类,说明这是一个bean,当然,现在还不能直接生成,我们需要判断一下是单例bean,还是一个多例(原型)bean  
package pri.study.spring;
import java.io.File;
import java.net.URL;
public class MyApplicationContext {
    private Class config;
    public MyApplicationContext (Class config) throws ClassNotFoundException {
        this.config = config;
        if (config.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScan = (ComponentScan) config.getAnnotation(ComponentScan.class);
            String sacnPath = componentScan.value();
            sacnPath = sacnPath.replace(".", "/");
            System.out.println("sacnPath = " + sacnPath);
            ClassLoader classLoader = MyApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(sacnPath);
            File file = new File(resource.getFile());
            if (file.isDirectory()) {
                for (File tmpFile : file.listFiles()) {
                    System.out.println(tmpFile.getAbsolutePath());
                    String absolutePath = tmpFile.getAbsolutePath();
                    absolutePath = absolutePath.substring(absolutePath.indexOf("pri"), absolutePath.indexOf(".class")).replace("\\", ".");
                    System.out.println("absolutePath = " + absolutePath);
                    Class<?> aClass = classLoader.loadClass(absolutePath);
                    // 判断是否包含 @Component 注解
                    if (aClass.isAnnotationPresent(Component.class)) {
                        // 判断是否包含 @Scope 注解
                        if (aClass.isAnnotationPresent(Scope.class)) {
                            Scope annotation = aClass.getAnnotation(Scope.class);
                            String value = annotation.value();
                            //todo 判断是单例还是多例(原型)
                        }
                    }
                }
            }
        }
    }
    public Object getBean (String beanName) {
        return null;
    }
}
  
package pri.study.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.TYPE)
public @interface Scope {
    String value() default "";
}
  
假设,我们判断完了,是一个单例,那就开始创建bean吗?  
想一个问题,我们是用 getBean() 方法,获取到的,传进去的一个beanname,返回了一个对象,所以是要用一个beanname来获取对应的类,如果我们找到类之后,还是得判断是单例还是多例的,又得进行和构造方法的内容一样的逻辑,很麻烦,且没必要,那我们能不能在构造方法里,就执行完一堆逻辑存储起来bean的特性呢?让 getBean() 就是单纯的去判断是单例还是多例,单例就直接获取bean,不去执行过多的重复性逻辑  
为了保证构造方法的简单,我们将扫描判断的过程单独抽取一个方法出来  
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
 private void scanpath(Class config) throws ClassNotFoundException {
        if (config.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScan = (ComponentScan) config.getAnnotation(ComponentScan.class);
            String sacnPath = componentScan.value();
            sacnPath = sacnPath.replace(".", "/");
            ClassLoader classLoader = MyApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(sacnPath);
            File file = new File(resource.getFile());
            if (file.isDirectory()) {
                for (File tmpFile : file.listFiles()) {
                    String absolutePath = tmpFile.getAbsolutePath();
                    absolutePath = absolutePath.substring(absolutePath.indexOf("pri"), absolutePath.indexOf(".class")).replace("\\", ".");
                    Class<?> aClass = classLoader.loadClass(absolutePath);
                    // 判断是否包含 @Component 注解
                    if (aClass.isAnnotationPresent(Component.class)) {
                        // 获取到自定义的bean的名字
                        Component component = aClass.getAnnotation(Component.class);
                        String beanName = component.value();
                        BeanDefinition beanDefinition = new BeanDefinition();
                        beanDefinition.setBeanType(aClass);
                        // 判断是否包含 @Scope 注解
                        if (aClass.isAnnotationPresent(Scope.class)) {
                            Scope annotation = aClass.getAnnotation(Scope.class);
                            String value = annotation.value();
                            beanDefinition.setScope(value);
                        } else {
                            beanDefinition.setScope("singleton");
                        }
                        beanDefinitionMap.put(beanName, beanDefinition);
                    }
                }
            }
        }
    }  
在这里,我们还多了样东西,就是 BeanDefinition,对bean的定义  
package pri.study.spring;
public class BeanDefinition {
    private Class beanType;
    private String scope;
    private boolean isLazy;
    public Class getBeanType() {
        return beanType;
    }
    public void setBeanType(Class beanType) {
        this.beanType = beanType;
    }
    public String getScope() {
        return scope;
    }
    public void setScope(String scope) {
        this.scope = scope;
    }
    public boolean isLazy() {
        return isLazy;
    }
    public void setLazy(boolean lazy) {
        isLazy = lazy;
    }
}
  
我们在解析完扫描完对应的路径下后,就已经知道了所有bean的情况,我们将他们进行记录,放入一个map中,bean的名字为key,定义为value,这个时候,我们继续写构造方法,进行判断,如果是单例的,那我们就生成bean,为了方便,我们再做一个map,存储beanName和对应的bean,仔细想想,getBean()方法,是不是放一个map很方便?  
        // 创建单例bean
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            String key = entry.getKey();
            BeanDefinition beanDefinition = beanDefinitionMap.get(key);
            if (beanDefinition.getScope().equals("singleton")) {
                Object bean = createBean(key, beanDefinition);
                singletonPool.put(key, bean);
            }
        }  
为什么只放单例呢?因为多例每次都需要重新创建,所以没必要创建,可以在getBean()的时候,判断是不是多例,如果是多例,我们再创建bean  
那么问题来了,如何创建bean呢?既然单例和多例都需要创建bean,那我们抽取一个共用方法  
    private Object createBean (String beanName, BeanDefinition beanDefinition) throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException {
        Class clazz = beanDefinition.getBeanType();
        Constructor constructor = clazz.getConstructor();
        Object bean = constructor.newInstance();
        return bean;
    }  
这里为了简单,我们直接使用空参的构造方法  
到了这里我们就结束了,可以正常使用我们的spring了  
于是整个 xxxApplicationContext的代码就是  
package pri.study.spring;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
public class MyApplicationContext {
    private Class config;
    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    // 定义一个单例池
    private Map<String, Object> singletonPool = new HashMap<>();
    public MyApplicationContext (Class config) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        this.config = config;
        // 扫描
        scanpath(config);
        // 创建单例bean
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            String key = entry.getKey();
            BeanDefinition beanDefinition = beanDefinitionMap.get(key);
            if (beanDefinition.getScope().equals("singleton")) {
                Object bean = createBean(key, beanDefinition);
                singletonPool.put(key, bean);
            }
        }
    }
    private Object createBean (String beanName, BeanDefinition beanDefinition) throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException {
        Class clazz = beanDefinition.getBeanType();
        Constructor constructor = clazz.getConstructor();
        Object bean = constructor.newInstance();
        return bean;
    }
    private void scanpath(Class config) throws ClassNotFoundException {
        if (config.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScan = (ComponentScan) config.getAnnotation(ComponentScan.class);
            String sacnPath = componentScan.value();
            sacnPath = sacnPath.replace(".", "/");
            ClassLoader classLoader = MyApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(sacnPath);
            File file = new File(resource.getFile());
            if (file.isDirectory()) {
                for (File tmpFile : file.listFiles()) {
                    String absolutePath = tmpFile.getAbsolutePath();
                    absolutePath = absolutePath.substring(absolutePath.indexOf("pri"), absolutePath.indexOf(".class")).replace("\\", ".");
                    Class<?> aClass = classLoader.loadClass(absolutePath);
                    // 判断是否包含 @Component 注解
                    if (aClass.isAnnotationPresent(Component.class)) {
                        // 获取到自定义的bean的名字
                        Component component = aClass.getAnnotation(Component.class);
                        String beanName = component.value();
                        BeanDefinition beanDefinition = new BeanDefinition();
                        beanDefinition.setBeanType(aClass);
                        // 判断是否包含 @Scope 注解
                        if (aClass.isAnnotationPresent(Scope.class)) {
                            Scope annotation = aClass.getAnnotation(Scope.class);
                            String value = annotation.value();
                            beanDefinition.setScope(value);
                        } else {
                            beanDefinition.setScope("singleton");
                        }
                        beanDefinitionMap.put(beanName, beanDefinition);
                    }
                }
            }
        }
    }
    public Object getBean (String beanName) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        if (!beanDefinitionMap.containsKey(beanName)) {
            throw new RuntimeException("bean name is error");
        }
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if (beanDefinition.getScope().equals("singleton")) {
            // 说明是单例的
            return singletonPool.get(beanName);
        } else {
            // 说明是一个多例(原型)bean,每次都需要创建
            return createBean(beanName, beanDefinition);
        }
    }
}
  
我们来试试  
   
?并且支持单例和多例  
单例:  
   
多例  
   
多个bean  
   
?但是这样,我们每次使用注解还得自定义bean的名字,否则会报错,但是我们实际在使用spring的时候并不用指定,so,我们进行优化  
// 获取到自定义的bean的名字
                        Component component = aClass.getAnnotation(Component.class);
                        String beanName = component.value();
                        if ("".equals(beanName)) {
                            beanName = Introspector.decapitalize(aClass.getSimpleName());
                        }  
我们来试试看正常不正常  
   
?  
?----------------------------------分割线----------------------------------  
现在我们已经可以创建一个bean了,在spring里面,还有一个很重要的玩意,依赖注入  
我们先实现一下注解  
package pri.study.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.FIELD)
public @interface Autowired {
}
  
现在当然是不能用的,不信我们看结果  
package pri.study.spring;
@Component(value = "userService")
@Scope(value = "aad")
public class UserService {
    @Autowired
    private OrderService orderService;
    public void printMessage () {
        System.out.println("this is userService's method uotput");
        System.out.println("orderService = " + orderService);
    }
}
  
package pri.study.spring;
import java.lang.reflect.InvocationTargetException;
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        MyApplicationContext myApplicationContext = new MyApplicationContext(Appconfig.class);
        UserService userService = (UserService) myApplicationContext.getBean("userService");
        userService.printMessage();
    }
}
  
   
?想一下spring bean的创建流程,在生成bean之前,是不是有一步依赖注入,所以,我们需要改造我们的 createBean 方法  
    private Object createBean (String beanName, BeanDefinition beanDefinition) throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException {
        Class clazz = beanDefinition.getBeanType();
        Constructor constructor = clazz.getConstructor();
        Object bean = null;
        bean = constructor.newInstance();
        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(Autowired.class)) {
                field.setAccessible(true);
                field.set(bean, getBean(field.getName()));
            }
        }
        return bean;
    }  
当然,这里是一个简单实现,是直接从单例池去拿的,会存在问题  
1、循环依赖,这个不在这次的分享范围内,暂时认为是OK的  
2、流程上是先扫描了,假设创建userService这个bean,进行到了createBean,而内部注入的orderService还没有生成,我们会拿到一个空;所以我们可以加一个判断,如果为空,就创建bean  
    public Object getBean (String beanName) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        if (!beanDefinitionMap.containsKey(beanName)) {
            throw new RuntimeException("bean name is error");
        }
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if (beanDefinition.getScope().equals("singleton")) {
            // 说明是单例的
            Object singleBean = singletonPool.get(beanName);
            if (Objects.isNull(singleBean)) {
                singleBean = createBean(beanName, beanDefinition);
                singletonPool.put(beanName, singleBean);
            }
            return singleBean;
        } else {
            // 说明是一个多例(原型)bean,每次都需要创建
            return createBean(beanName, beanDefinition);
        }
    }  
   
在我的上篇文章分享里,介绍了spring bean的创建流程,还涉及到了初始化的东西,也来实现一下  
package pri.study.spring;
public interface InitializingBean {
    void afterPropertiesSet() throws Exception;
    
}
  
那么具体该怎么实现初始化后的东西呢?看下面,我们可以在createBean之后,判断有没有实现,有,那就强转调用,这个在上篇文档也说过  
    private Object createBean (String beanName, BeanDefinition beanDefinition) throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException {
        Class clazz = beanDefinition.getBeanType();
        Constructor constructor = clazz.getConstructor();
        Object bean = null;
        bean = constructor.newInstance();
        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(Autowired.class)) {
                field.setAccessible(true);
                field.set(bean, getBean(field.getName()));
            }
        }
        // 判断是否实现了 InitializingBean,如果实现了,那就强转,然后调用
        if (bean instanceof InitializingBean) {
            ((InitializingBean) bean).afterPropertiesSet();
        }
        return bean;
    }  
?----------------------------------分割线----------------------------------?  
在spring中,还有一个很重要的接口,BeanPostProcessor ,这个接口有两个方法 postProcessBeforeInitialization 和 postProcessAfterInitialization,这个接口的方法,是针对于所有的bean的,也就是说,如果实现了这个接口,所有的bean都会调用重写的这两个方法  
至于该怎么调用呢,其实也简单,我们只要在bean生成之前,判断有没有这个接口的实现,实现了这个接口,那我们就保存下来,在创建完bean之后,去使用,因为可能有多实现,所以我们放在list,然后我们在创建完bean之后,遍历这个集合,进行执行  
private void scanpath(Class config) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        if (config.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScan = (ComponentScan) config.getAnnotation(ComponentScan.class);
            String sacnPath = componentScan.value();
            sacnPath = sacnPath.replace(".", "/");
            ClassLoader classLoader = MyApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(sacnPath);
            File file = new File(resource.getFile());
            if (file.isDirectory()) {
                for (File tmpFile : file.listFiles()) {
                    String absolutePath = tmpFile.getAbsolutePath();
                    absolutePath = absolutePath.substring(absolutePath.indexOf("pri"), absolutePath.indexOf(".class")).replace("\\", ".");
                    Class<?> aClass = classLoader.loadClass(absolutePath);
                    // 判断是否包含 @Component 注解
                    if (aClass.isAnnotationPresent(Component.class)) {
                        // 判断是否有bean实现了 BeanPostProcessor 接口,如果有,就存下来
                        if (BeanPostProcessor.class.isAssignableFrom(aClass)) {
                            BeanPostProcessor beanPostProcessor = (BeanPostProcessor) aClass.getConstructor().newInstance();
                            beanPostProcessorList.add(beanPostProcessor);
                        }
                        // 获取到自定义的bean的名字
                        Component component = aClass.getAnnotation(Component.class);
                        String beanName = component.value();
                        if ("".equals(beanName)) {
                            beanName = Introspector.decapitalize(aClass.getSimpleName());
                        }
                        BeanDefinition beanDefinition = new BeanDefinition();
                        beanDefinition.setBeanType(aClass);
                        // 判断是否包含 @Scope 注解
                        if (aClass.isAnnotationPresent(Scope.class)) {
                            Scope annotation = aClass.getAnnotation(Scope.class);
                            String value = annotation.value();
                            beanDefinition.setScope(value);
                        } else {
                            beanDefinition.setScope("singleton");
                        }
                        beanDefinitionMap.put(beanName, beanDefinition);
                    }
                }
            }
        }
    }  
private Object createBean (String beanName, BeanDefinition beanDefinition) throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException {
        Class clazz = beanDefinition.getBeanType();
        Constructor constructor = clazz.getConstructor();
        Object bean = null;
        bean = constructor.newInstance();
        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(Autowired.class)) {
                field.setAccessible(true);
                field.set(bean, getBean(field.getName()));
            }
        }
        // 判断是否实现了 InitializingBean,如果实现了,那就强转,然后调用
        if (bean instanceof InitializingBean) {
            ((InitializingBean) bean).afterPropertiesSet();
        }
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
            beanPostProcessor.postProcessAfterInitialization(bean, beanName);
        }
        return bean;
    }  
   
?仔细看一个东西,BeanPostProcessor 的方法是有返回值的,意味着我们可以把bean返回去,想一想,我们可以对bean做更改,然后返回去,有没有很熟悉?就是AOP,我们完全可以在方法内对指定的bean进行代理,然后返回代理对象,将外部的bean进行更改,改为代理对象 
                
        
    
 
 |