Spring原理(一)生命周期

容器BeanFactory

/**
 * 容器:保存bean,获取bean
 */
public class BeanFactory {
    private Map<String, Object> beanMap = new HashMap<>();

    public void registerBean(String name, Object bean) {
        beanMap.put(name, bean);
    }

    public Object getBean(String name) {
        return beanMap.get(name);
    }
}

BeanDefinition

在这里插入图片描述

/**
 * BeanDefinition实例保存bean的信息
 * 包括class类型、方法构造参数、是否为单例
 */
@Data
@AllArgsConstructor
public class BeanDefinition {
    private Class beanClass;
}
public interface BeanFactory {
    /**
     * 容器获取bean
     * @param name
     * @return
     * @throws BeansException bean不存在抛出异常
     */
    Object getBean(String name) throws BeansException;
}
public class BeansException extends RuntimeException{
    public BeansException(String msg, Exception e) {
        super(msg, e);
    }
}
public interface BeanDefinitionRegister {
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
}
/**
 * 单例注册表
 */
public interface SimpletonBeanRegister {
    Object getSingleton(String beanName);
}
public class DefaultSingletonBeanRegister implements SimpletonBeanRegister{
    private final Map<String, Object> singletonObjects = new HashMap<>();

    @Override
    public Object getSingleton(String beanName) {
        return singletonObjects.get(beanName);
    }

    protected void addSingleton(String beanName, Object singletonObject) {
        singletonObjects.put(beanName, singletonObject);
    }
}
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegister implements BeanFactory{
    @Override
    public Object getBean(String beanName) throws BeansException {
        Object bean = getSingleton(beanName);
        if (bean != null) {
            return bean;
        }

        // 如果容器中不存在该对象就创建一个
        BeanDefinition beanDefinition = getBeanDefinition(beanName);
        return createBean(beanName, beanDefinition);
    }

    protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;

    protected abstract Object createBean(String name, BeanDefinition beanDefinition) throws BeansException;
}
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {

    @Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
        return doCreateBean(beanName, beanDefinition);
    }

    protected Object doCreateBean(String beanName, BeanDefinition beanDefinition) {
        Class beanClass = beanDefinition.getBeanClass();
        Object bean = null;
        try {
            // 反射创建对象
            bean = beanClass.newInstance();
        } catch (Exception e) {
            throw new BeansException("instantiation of bean failed", e);
        }

        // 加入到容器中
        addSingleton(beanName, bean);

        return bean;
    }
}
/**
 * 供外界使用的工厂
 */
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegister{
    private final Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();

    @Override
    protected BeanDefinition getBeanDefinition(String beanName) throws BeansException {
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if(beanDefinition == null) {
            throw new BeansException("no bean named '" + beanName + "' id defined", null);
        }
        return beanDefinition;
    }

    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
        beanDefinitionMap.put(beanName, beanDefinition);
    }
}

Bean实例化策略InstantiationStrategy

  1. 以前bean在AbstractAutowireCapableBeanFactory.doCreateBean方法中用beanClass.newInstance()来实例化,仅适用于bean有无参构造函数的时候。
  2. 抽象出实例化策略的接口InstantiationStrategy,两个实现类
  3. SimpleInstantiationStrategy,使用bean的构造函数来实例化。
  4. CglibSubclassingInstantiationStrategy,使用CGLIB动态生成子类。
/**
 * bean实例化策略接口
 */
public interface InstantiationStrategy {
    Object instantiate(BeanDefinition beanDefinition) throws BeansException;
}
/**
 * 使用bean的构造函数进行实例化
 */
public class SimpleInstantiationStrategy implements InstantiationStrategy {

    @Override
    public Object instantiate(BeanDefinition beanDefinition) throws BeansException {
        Class beanClass = beanDefinition.getBeanClass();
        try {
            // 使用无参构造函数实例化对象
            Constructor constructor = beanClass.getDeclaredConstructor();
            return constructor.newInstance();
        } catch (Exception e) {
            throw new BeansException("failed to instantiate [" + beanClass.getName() + "]", e);
        }
    }
}
/**
 * 使用cglib生成代理对象
 */
public class CglibSubclassingInstantiationStrategy implements InstantiationStrategy{
    @Override
    public Object instantiate(BeanDefinition beanDefinition) throws BeansException {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(beanDefinition.getBeanClass());
        enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> proxy.invokeSuper(obj, args));
        return enhancer.create();
    }
}

bean填充属性

  1. BeanDefinition中增加属性对应的PropertyValues属性,为bean填充属性。
/**
 * bean的信息描述
 */
public class PropertyValue {
    private final String name;
    private final Object value;

    public PropertyValue(String name, Object value) {
        this.name = name;
        this.value = value;
    }

    public String getName() {
        return name;
    }

    public Object getValue() {
        return value;
    }
}
public class PropertyValues {
    private final List<PropertyValue> propertyValueList = new ArrayList<>();

    public void addPropertyValue(PropertyValue pv) {
        this.propertyValueList.add(pv);
    }

    public PropertyValue[] getPropertyValueList() {
        return this.propertyValueList.toArray(new PropertyValue[0]);
    }

    public PropertyValue getPropertyValue(String propertyName) {
        for (PropertyValue propertyValue : propertyValueList) {
            if(propertyValue.getName().equals(propertyName)) {
                return propertyValue;
            }
        }

        return null;
    }
}
  1. BeanDefinition新增PropertyValues属性。
/**
 * BeanDefinition实例保存bean的信息
 * 包括class类型、方法构造参数、是否为单例
 */
@Data
@AllArgsConstructor
public class BeanDefinition {
    public BeanDefinition(Class beanClass) {
        this.beanClass = beanClass;
    }

    private Class beanClass;

    /**
     * 属性的集合
     */
    private PropertyValues propertyValues;
}
  1. AbstractAutowireCapableBeanFactory在创建bean的时候,新增applyPropertyValues为bean填充属性。
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
    /**
     * 创建一个实例化bean的策略对象
     */
    private InstantiationStrategy instantiationStrategy = new SimpleInstantiationStrategy();

    public InstantiationStrategy getInstantiationStrategy() {
        return instantiationStrategy;
    }

    public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
        this.instantiationStrategy = instantiationStrategy;
    }

    @Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
        return doCreateBean(beanName, beanDefinition);
    }

    protected Object doCreateBean(String beanName, BeanDefinition beanDefinition) {
        Object bean = null;
        try {
            // 创建一个bean
            bean = createBeanInstance(beanDefinition);
            // 填充bean属性
            applyPropertyValues(beanName, bean, beanDefinition);
        } catch (Exception e) {
            throw new BeansException("instantiation of bean failed", e);
        }

        // 加入到容器中
        addSingleton(beanName, bean);

        return bean;
    }

    protected Object createBeanInstance(BeanDefinition beanDefinition) {
        // 使用实例化策略创建对象
        return getInstantiationStrategy().instantiate(beanDefinition);
    }

    /**
     * 为bean填充属性
     * @param beanName
     * @param bean
     * @param beanDefinition
     */
    protected void applyPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition) {
        try {
            PropertyValues propertyValues = beanDefinition.getPropertyValues();
            for (PropertyValue propertyValue : propertyValues.getPropertyValueList()) {
                String name = propertyValue.getName();
                Object value = propertyValue.getValue();

                // 反射设置属性值
                BeanUtils.setFieldValue(bean, name, value);
            }
        } catch (Exception e) {
            throw new BeansException("Error setting property values for bean: " + beanName, e);
        }
    }
}
  1. 新增BeanUtils工具类,使用反射设置bean的属性。
public class BeanUtils {
    /**
     * 设置bean的属性property
     * @param bean bean对象
     * @param name 属性名
     * @param value 属性值
     */
    public static void setFieldValue(Object bean, String name, Object value) throws NoSuchFieldException, IllegalAccessException {
        Class<?> clazz = bean.getClass();
        Field field = clazz.getDeclaredField(name);
        field.setAccessible(true);
        field.set(bean, value);
    }
}

Confiuration后置处理器测试

  1. ConfigurationClassPostProcessor后置处理器,解析@Configration注解。
public class TestBeanFactory {
    public static void main(String[] args) {
        // 创建一个BeanFactory的实现
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // 创建一个Config的BeanDefinition
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Config.class);
        AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.setScope("singleton").getBeanDefinition();

        // 将BeanDefinition注册到容器中
        beanFactory.registerBeanDefinition("config", beanDefinition);

        // 给BeanFactory中的bean添加一些常用的后置处理器
        // 比如ConfigurationClassPostProcessor后置处理器,就是解析bean中的Configuration注解
        // 但是把这些后置处理器加入到容器中,还没有运行
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

        // 从容器中获取这些后置处理器
        Map<String, BeanFactoryPostProcessor> postProcessMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
        postProcessMap.values().forEach(beanFactoryPostProcessor -> {
            // 执行每个后置处理器的后置方法,
            // ConfigurationClassPostProcessor后置处理器就会解析Configuration注解
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });


        // 只执行ConfigurationClassPostProcessor的后置处理器
//        ConfigurationClassPostProcessor postProcessor = beanFactory.getBean(ConfigurationClassPostProcessor.class);
//        postProcessor.postProcessBeanFactory(beanFactory);

        // 打印容器中BeanDefinition的名字
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
    }

    @Configuration
    static class Config {
        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2() {
            return new Bean2();
        }
    }

    static class Bean1 {
        @Autowired
        private Bean2 bean2;

        public Bean1() {
            System.out.println("bean1 创建");
        }

        public Bean2 getBean2() {
            return bean2;
        }
    }

    static class Bean2 {
        public Bean2() {
            System.out.println("bean2 创建");
        }
    }
}

ClassPathXmlApplicationContext原理

public class TestApplicationContext {
    public static void main(String[] args) {
//        ClassPathXmlApplicationContext beanFactory = new ClassPathXmlApplicationContext("spring.xml");

        /*
         * ClassPathXmlApplicationContext 原理
         */

        // 创建一个BeanFactory
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 读取XML的BeanDefinition解析器,解析出来的BeanDefinition放到beanFactory中
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        // 加载解析文件
        beanDefinitionReader.loadBeanDefinitions("spring.xml");

        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

        Bean1 bean1 = beanFactory.getBean(Bean1.class);
        System.out.println(bean1.getBean2());
    }

    static class Bean1 {
        private Bean2 bean2;

        public Bean1() {
            System.out.println("创建bean1.....");
        }

        public void setBean2(Bean2 bean2) {
            this.bean2 = bean2;
        }

        public Bean2 getBean2() {
            return bean2;
        }
    }

    static class Bean2 {
        public Bean2() {
            System.out.println("创建bean2...");
        }
    }
}

AnnotationConfigServletWebServerApplicationContext

  1. 基于Web环境的sevlet容器。
  2. 该程序要运行在SpringBoot中,因为只有SpringBoot才内嵌了Tomcat容器
  3. 运行该程序,在游览器访问http://localhost:8080/hello就可以收到回复。
public class TestWebServerApplication {
    public static void main(String[] args) {
        // web环境的servlet容器ApplicationContext
        AnnotationConfigServletWebServerApplicationContext webServerApplicationContext =
                new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
    }

    @Configuration
    static class WebConfig {
        @Bean
        public ServletWebServerFactory servletWebServerFactory() {
            // 创建一个基于tomcat的web servlet实现
            return new TomcatServletWebServerFactory();
        }

        @Bean
        public DispatcherServlet dispatcherServlet() {
            return new DispatcherServlet();
        }

        @Bean
        public DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet) {
            // 将DispatcherServlet注册到容器中,“/”表示所有请求都经过servlet处理器
            return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
        }

        /**
         * 在容器中加入一个controller
         * @return Controller接口,不是注解
         */
        @Bean("/hello")
        public Controller controller() {
            return new Controller() {
                @Override
                public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
                    // 向页面写一个hello
                    response.getWriter().print("hello");
                    return null;
                }
            };
        }
    }
}

测试Bean生命周期

  1. 构造方法 -> 依赖注入 -> 初始化
@SpringBootApplication
public class SpringBootApplicationTest {
    public static void main(String[] args) {
        // 获取applicationContext
        ConfigurableApplicationContext applicationContext = SpringApplication.run(SpringBootApplicationTest.class, args);
        MyBeanPostProcessor bean = applicationContext.getBean(MyBeanPostProcessor.class);
        System.out.println(bean);
        // 关闭容器,方便观察bean生命周期方法
        applicationContext.close();
    }
}
  1. 演示bean的生命周期
/**
 * 测试bean的生命周期
 */
@Component
public class LifeCycleBean {
    public LifeCycleBean() {
        System.out.println("构造方法");
    }

    @Autowired
    public void getHome(@Value("${JAVA_HOME}") String home) {
        System.out.println("依赖注入:home = " + home);
    }

    /**
     * PostConstruct注解是在依赖注入之后执行
     * 在CommonAnnotationBeanPostProcessor后置处理器中,处理PostConstruct、PreDestroy
     */
    @PostConstruct
    public void init() {
        System.out.println("bean初始化");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("销毁方法");
    }
}
  1. 自定义后置处理器
/**
 * InstantiationAwareBeanPostProcessor: 构造方法前后、初始化前后
 * DestructionAwareBeanPostProcessor:销毁之前
 */
@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if ("lifeCycleBean".equals(beanName)) {
            System.out.println("执行构造方法之前...");
        }

        // 这里返回的对象会替换原来的bean
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if ("lifeCycleBean".equals(beanName)) {
            System.out.println("执行构造方法之后...");
        }

        // 如果返回false,就会跳过依赖注入阶段
        return true;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("lifeCycleBean".equals(beanName)) {
            System.out.println("初始化之前...");
        }

        // 这里返回的对象会替换到原来的bean
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("lifeCycleBean".equals(beanName)) {
            System.out.println("初始化之后...");
        }

        // 这里返回的对象会替换原来的bean,如代理增强
        return bean;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if ("lifeCycleBean".equals(beanName)) {
            System.out.println("依赖注入阶段 如@Autowird、@Value、@Resource...");
        }

        return pvs;
    }

    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        if ("lifeCycleBean".equals(beanName)) {
            System.out.println("销毁方法之前...");
        }
    }
}

模板方法模式

public class TestMethodTemplate {
    public static void main(String[] args) {
        MyBeanFactory myBeanFactory = new MyBeanFactory();
        // 创建后置处理器
        myBeanFactory.addPostProcessor(obj -> System.out.println("解析 @Autowired"));
        myBeanFactory.addPostProcessor(obj -> System.out.println("解析 @Resource"));

        myBeanFactory.getBean();
    }

    static class MyBeanFactory {
        private final List<BeanPostProcessor> postProcessors = new ArrayList<>();

        public void addPostProcessor(BeanPostProcessor beanPostProcessor) {
            postProcessors.add(beanPostProcessor);
        }

        public Object getBean() {
            Object o = new Object();
            System.out.println("构造方法");
            System.out.println("依赖注入");
            // 解析@Autowired、@Resource
            for (BeanPostProcessor postProcessor : postProcessors) {
                postProcessor.inject(o);
            }

            System.out.println("初始化");

            return o;
        }
    }

    static interface BeanPostProcessor {
        void inject(Object obj);
    }
}

Autowired后置处理器

public class TestBeanPostProcessor {
    public static void main(String[] args) {
        GenericApplicationContext applicationContext = new GenericApplicationContext();

        applicationContext.registerBean(BeanTest1.class);
        applicationContext.registerBean(BeanTest2.class);

        /*
            注册bean的后置处理器
         */
        // 解析@Value注解
        applicationContext.getDefaultListableBeanFactory().setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        // 处理@Autowird
        applicationContext.registerBean(AutowiredAnnotationBeanPostProcessor.class);
        // 处理@Resource、@PostConstruct、@PreDestroy
        applicationContext.registerBean(CommonAnnotationBeanPostProcessor.class);

        // SpringBoot中的解析@ConfigurationProperties的后置处理器
        ConfigurationPropertiesBindingPostProcessor.register(applicationContext.getDefaultListableBeanFactory());

        // 执行BeanFactory后置处理器,bean的后置处理器,初始化所有单例
        applicationContext.refresh();

        // 销毁容器
        applicationContext.close();
    }
}

class BeanTest1 {
    private BeanTest2 beanTest2;

    @Autowired
    public void setBeanTest2(BeanTest2 beanTest2) {
        System.out.println("@Autowired生效,beanTest2 = " + beanTest2);
        this.beanTest2 = beanTest2;
    }

    @Autowired
    public void setHome(@Value("${JAVA_HOME}") String home) {
        System.out.println("@Value生效,home = " + home);
    }

    public BeanTest1() {
        System.out.println("构造方法...");
    }

    @PostConstruct
    public void init() {
        System.out.println("@PostConstruct生效,初始化前...");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("@PreDestroy生效,销毁...");
    }
}

class BeanTest2 {}

Autowired注解解析过程

  1. Autowired注解的解析后置处理器:AutowiredAnnotationBeanPostProcessor
public class TestAutowired {
    public static void main(String[] args) throws Throwable {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("beanTest2", new BeanTest2());
        // 加入@Value的解析器
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        // 对${}符号解析
        beanFactory.addEmbeddedValueResolver(new StandardEnvironment() :: resolvePlaceholders);

        AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
        autowiredAnnotationBeanPostProcessor.setBeanFactory(beanFactory);

        BeanTest1 beanTest1 = new BeanTest1();
        System.out.println(beanTest1);
        /**
         * 方式一:直接调用autowired的postProcessProperties方法
         */
        // autowiredAnnotationBeanPostProcessor.postProcessProperties(null, beanTest1, "beanTest1");

        /**
         * 方式二:通过反射执行内部的方法
         */
        // 反射获取私有方法findAutowiringMetadata,该方法找到标注@Autowired的属性或方法
        Method findAutowiringMetadata = autowiredAnnotationBeanPostProcessor.getClass().getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        findAutowiringMetadata.setAccessible(true);
        // 执行该方法,找到表示@Autowired的属性和方法
        InjectionMetadata metadata = (InjectionMetadata) findAutowiringMetadata.invoke(autowiredAnnotationBeanPostProcessor, "beanTest1", BeanTest1.class, null);

        // 执行依赖注入方法
        metadata.inject(beanTest1, "beanTest1", null);
        System.out.println(beanTest1);

        /**
         * metadata.inject内部如何按类型找到值
         */
        Field beanTest2 = BeanTest1.class.getDeclaredField("beanTest2");
        // 将反射的属性,封装成DependencyDescriptor对象
        DependencyDescriptor dd1 = new DependencyDescriptor(beanTest2, true);
        // 在容器中找该对象
        Object o = beanFactory.resolveDependency(dd1, null);
        System.out.println(o);
    }
}

BeanFactory的后置处理器

  1. BeanFactory的后置处理器,主要对BeanFactory做一些增强。
/**
 * BeanFactory的后置处理器,对BeanFactory进行增强
 */
public class TestBeanFactoryPostProcessor {
    public static void main(String[] args) {
        // 创建一个干净的容器
        GenericApplicationContext applicationContext = new GenericApplicationContext();
        applicationContext.registerBean(Config.class);
        // 加入BeanFactory的后置处理器:解析@ComponentScan @Bean @Import @ImportResource等注解
        applicationContext.registerBean(ConfigurationClassPostProcessor.class);

        // MapperScannerConfigurer这个后置处理器是Mybatis提供的
        // 用于扫描MapperScanner Mapper注解
        applicationContext.registerBean(MapperScannerConfigurer.class, bd -> {
            // 设置扫描的包路径
            bd.getPropertyValues().add("basePackage", "mapper");
        });
        applicationContext.refresh();

        // 查看容器中有那些bean
        for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

        applicationContext.close();
    }
}
@Configuration
@ComponentScan("moudle")
public class Config {
    @Bean
    public Bean1 bean1() {
        return new Bean1();
    }

    /**
     * 引入了mybatis的依赖,必须加入SqlSessionFactoryBean和DataSource
     * @param dataSource
     * @return
     */
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        return sqlSessionFactoryBean;
    }

    @Bean
    public DataSource dataSource() {
        PooledDataSource pooledDataSource = new PooledDataSource();
        pooledDataSource.setUrl("jdbc:mysql://localhost:3306/abc");
        pooledDataSource.setUsername("root");
        pooledDataSource.setPassword("abc");
        return pooledDataSource;
    }
}

自己解析ComponentScan注解

/**
 * 自定义ComponentScan注解的扫描类
 */
public class ComponentScanPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        try {
            /**
             * 模拟Spring解析ComponentScan和Component的流程
             */
            // 先使用Spring的工具类AnnotationUtils,查看Config配置类中,有没有ComponentScan
            Optional<ComponentScan> optional = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
            if (optional.isPresent()) {
                // 获取ComponentScan注解上配置的扫描包路径
                ComponentScan componentScan = optional.get();
                PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
                for (String basePackage : componentScan.value()) {
                    // 如果包名是:com.moudle,转化为classpath*:com/moudle/**/*.class的资源路径
                    String path = "classpath*:" + basePackage.replace(".", "/") + "/**/*.class";
                    // 获取资源路径的class文件
                    Resource[] resources = resolver.getResources(path);
                    // 创建一个读取类的源信息的工厂
                    CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
                    AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
                    if (beanFactory instanceof DefaultListableBeanFactory) {
                        DefaultListableBeanFactory beanFactory1 = (DefaultListableBeanFactory) beanFactory;
                        for (Resource resource : resources) {
                            // 判断该class文件有没有Component注解
                            // 获取类源信息
                            MetadataReader metadataReader = factory.getMetadataReader(resource);
                            AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
                            System.out.println("类名:" + metadataReader.getClassMetadata().getClassName());
                            // 如果要查找component的派生注解,比如@Controller注解,要使用hasMetaAnnotation
                            System.out.println("是否包含component注解:" + annotationMetadata.hasAnnotation(Component.class.getName()));
                            System.out.println("是否包含component的派生词注解:" + annotationMetadata.hasMetaAnnotation(Component.class.getName()));

                            // 如果有Component或它的派生注解,就生成一个BeanDefinition,加入到容器中
                            if (annotationMetadata.hasAnnotation(Component.class.getName()) ||
                                    annotationMetadata.hasMetaAnnotation(Component.class.getName())) {

                                // 类信息生成一个BeanDefinition
                                AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(metadataReader.getClassMetadata().getClassName()).getBeanDefinition();
                                // 生成一个bean的名字
                                String beanName = generator.generateBeanName(beanDefinition, beanFactory1);
                                beanFactory1.registerBeanDefinition(beanName, beanDefinition);
                            }
                        }
                    }

                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
/**
 * 解析@Bean注解的属性
 */
public class AtBeanPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        try {
            /**
             * 解析Config配置类里面的@Bean注解
             */
            // 读取类的源数据
            CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
            // 读取Config的类信息,不会将Config加载到JVM内存中
            MetadataReader metadataReader = factory.getMetadataReader(new ClassPathResource("Config.class"));
            AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
            // 获取Config类上,标注了Bean注解的方法
            Set<MethodMetadata> methods = annotationMetadata.getAnnotatedMethods(Bean.class.getName());
            for (MethodMetadata method : methods) {
                // 找到标注了Bean注解的方法
                System.out.println(method.getMethodName());
                // 获取bean注解的属性进行设置, 找到bean的初始化方法
                String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();

                BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
                if (initMethod.length() > 0) {
                    // 设置bean的初始化方法
                    builder.setInitMethodName(initMethod);
                }

                // 设置工厂方法的参数,按照构造器进行注入
                builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
                // 使用工厂方法创建BeanDefinition的实例: 第一个参数是工厂方法的名称,第二个参数是执行的工厂类
                builder.setFactoryMethodOnBean(method.getMethodName(), "Config");
                AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
                if (beanFactory instanceof DefaultListableBeanFactory) {
                    DefaultListableBeanFactory beanFactory1 = (DefaultListableBeanFactory) beanFactory;
                    beanFactory1.registerBeanDefinition(method.getMethodName(), beanDefinition);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
/**
 * BeanFactory的后置处理器,对BeanFactory进行增强
 */
public class TestBeanFactoryPostProcessor {
    public static void main(String[] args) throws IOException {
        // 创建一个干净的容器
        GenericApplicationContext applicationContext = new GenericApplicationContext();
        applicationContext.registerBean(Config.class);
        // 加入BeanFactory的后置处理器:解析@ComponentScan @Bean @Import @ImportResource等注解
//        applicationContext.registerBean(ConfigurationClassPostProcessor.class);

        // 自定义ComponentScan注解解析器
        applicationContext.registerBean(ComponentScanPostProcessor.class);
        
		// 解析@Bean注解中的属性
        applicationContext.registerBean(AtBeanPostProcessor.class);

        applicationContext.refresh();
        // 查看容器中有那些bean
        for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

        applicationContext.close();
    }
}

解析Mapper注解

  1. Spring底层将Mapper接口加入到Spring容器中,使用的是如下配置。
@Configuration
@ComponentScan("moudle")
public class Config {

	/**
     * 引入了mybatis的依赖,必须加入SqlSessionFactoryBean和DataSource
     * @param dataSource
     * @return
     */
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        return sqlSessionFactoryBean;
    }

    @Bean
    public DataSource dataSource() {
        PooledDataSource pooledDataSource = new PooledDataSource();
        pooledDataSource.setUrl("jdbc:mysql://localhost:3306/abc");
        pooledDataSource.setUsername("root");
        pooledDataSource.setPassword("abc");
        return pooledDataSource;
    }

    /**
     * 将Mapper1接口加入到Spring中
     * @param sqlSessionFactory
     * @return
     */
    @Bean
    public MapperFactoryBean<Mapper1> mapper1(SqlSessionFactory sqlSessionFactory) {
        MapperFactoryBean<Mapper1> factory = new MapperFactoryBean<>(Mapper1.class);
        factory.setSqlSessionFactory(sqlSessionFactory);
        return factory;
    }
}
  1. 自定义解析Mapper注解。
/**
 * 解析@Mapper注解
 */
public class MapperPostProcessor implements BeanDefinitionRegistryPostProcessor {
    /**
     * 这里实现BeanDefinitionRegistryPostProcessor接口,可以直接拿到DefaultListableBeanFactory
     * 相对于实现BeanFactoryPostProcessor接口,不用进行强转
     * @param registry
     * @throws BeansException
     */
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        try {
            // 扫描mapper包
            PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            Resource[] resources = resolver.getResources("classpath:mapper/**/*.class");
            CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
            AnnotationBeanNameGenerator annotationBeanNameGenerator = new AnnotationBeanNameGenerator();
            for (Resource resource : resources) {
                MetadataReader metadataReader = factory.getMetadataReader(resource);
                ClassMetadata classMetadata = metadataReader.getClassMetadata();
                // 判断该Mapper类是不是接口
                if (classMetadata.isInterface()) {
                    // 为MapperFactoryBean类创建一个BeanDefinition
                    // MapperFactoryBean是创建Mapper的工厂
                    AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class)
                            // 为工厂的构造方法,填入该mapper的类名
                            .addConstructorArgValue(classMetadata.getClassName())
                            // 按类型填充参数,就是在容器中找到SqlSessionFactory,进行注入
                            .setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE)
                            .getBeanDefinition();

                    // 在创建一个Mapper类的BeanDefinition
                    AbstractBeanDefinition mapperBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition(classMetadata.getClassName())
                            .getBeanDefinition();

                    // 为Mapper接口创建一个名字
                    String name = annotationBeanNameGenerator.generateBeanName(mapperBeanDefinition, registry);
                    registry.registerBeanDefinition(name, beanDefinition);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}
  1. 加入后置处理器
/**
 * BeanFactory的后置处理器,对BeanFactory进行增强
 */
public class TestBeanFactoryPostProcessor {
    public static void main(String[] args) throws IOException {
        // 创建一个干净的容器
        GenericApplicationContext applicationContext = new GenericApplicationContext();
        applicationContext.registerBean(Config.class);
        // 加入BeanFactory的后置处理器:解析@ComponentScan @Bean @Import @ImportResource等注解
//        applicationContext.registerBean(ConfigurationClassPostProcessor.class);

        // 自定义ComponentScan注解解析器
        applicationContext.registerBean(ComponentScanPostProcessor.class);

        // 解析@Bean注解中的属性
        applicationContext.registerBean(AtBeanPostProcessor.class);

        // 解析@Mapper注解
        applicationContext.registerBean(MapperPostProcessor.class);

        applicationContext.refresh();
        // 查看容器中有那些bean
        for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

        applicationContext.close();
    }
}

Aware和InitializingBean

  1. Aware接口在初始化之前进行回调。InitializingBean初始化回调。
public class MyBean implements BeanNameAware, ApplicationContextAware, InitializingBean {
    @Override
    public void setBeanName(String name) {
        System.out.println("bean的名称:" + name);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("容器对象: " + applicationContext);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("初始化方法...");
    }
}
public class TestAware {
    public static void main(String[] args) {
        GenericApplicationContext applicationContext = new GenericApplicationContext();
        applicationContext.registerBean("myBean", MyBean.class);
        applicationContext.refresh();
        applicationContext.close();
    }
}
  1. Aware接口和@Autowired注入有什么区别,InitializingBean和@PostContustruct注解有什么区别?
  2. 后者使用注解需要额外有后置处理器进行处理才能生效。
public class MyBean implements BeanNameAware, ApplicationContextAware, InitializingBean {
    @Override
    public void setBeanName(String name) {
        System.out.println("bean的名称:" + name);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("容器对象: " + applicationContext);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("初始化方法...");
    }

    @Autowired
    public void a(ApplicationContext applicationContext) {
        System.out.println("Autowired 注入bean");
    }

    @PostConstruct
    public void init() {
        System.out.println("PostConstruct 进行初始化...");
    }
}

public class TestAware {
    public static void main(String[] args) {
        GenericApplicationContext applicationContext = new GenericApplicationContext();
        applicationContext.registerBean("myBean", MyBean.class);
        // 解析Autowired
        applicationContext.registerBean(AutowiredAnnotationBeanPostProcessor.class);
        // 解析PostConstruct
        applicationContext.registerBean(CommonAnnotationBeanPostProcessor.class);
        applicationContext.refresh();
        applicationContext.close();
    }
}

Autowired失效问题

  1. 在配置类中加入一个BeanFactoryPostProcessor后置处理器,会使@Autowired失效。
@Configuration
public class MyConfig1 {
    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        System.out.println("Autowired 注入,applicationContext = " + applicationContext);
    }

    @PostConstruct
    public void init() {
        System.out.println("MyConfig1初始化...");
    }

    /**
     * 注入下面这个bean,上面这两个会失效
     * @return
     */
    @Bean
    public BeanFactoryPostProcessor beanFactoryPostProcessor() {
        System.out.println("注入一个beanFactoryPostProcessor...");
        return beanFactory -> {
            System.out.println("运行beanFactoryPostProcessor...");
        };
    }
}
public class TestAware {
    public static void main(String[] args) {
        GenericApplicationContext applicationContext = new GenericApplicationContext();
        applicationContext.registerBean("MyConfig1", MyConfig1.class);
        // 解析Autowired
        applicationContext.registerBean(AutowiredAnnotationBeanPostProcessor.class);
        // 解析PostConstruct
        applicationContext.registerBean(CommonAnnotationBeanPostProcessor.class);
        // 解析@Bean
        applicationContext.registerBean(ConfigurationClassPostProcessor.class);
        applicationContext.refresh();
        applicationContext.close();
    }
}
  1. 原始的javaBean初始化流程:

在这里插入图片描述

  1. 加入一个BeanFactoryPostProcessor后,就必须提前创建Java配置类,而此时BeanPostProcessor还未准备好,导致@Autowired等注解失效。

在这里插入图片描述

  1. 使用Aware接口和InitializingBean接口就可以避免这个问题。
@Configuration
public class MyConfig2 implements ApplicationContextAware, InitializingBean {

    @Bean
    public BeanFactoryPostProcessor beanFactoryPostProcessor() {
        System.out.println("注入一个beanFactoryPostProcessor...");
        return beanFactory -> {
            System.out.println("运行myConfig2, beanFactoryPostProcessor...");
        };
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("初始化MyConfig2");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("aware applicationContext = " + applicationContext);
    }
}
  1. 学到什么:
  2. Aware接口提供一种内置的注入手段,可以注入BeanFactory,ApplicationContext。
  3. InitializingBean接口提供一种内置的初始化手段。
  4. 内置的注入和初始化不受扩展功能的影响,总会被执行,因此Spring框架内部的类常用他们。

bean初始化和销毁

  1. bean的初始化有三种方法:@PostConstruct、实现InitializingBean接口、通过@Bean注解的initMethod指定。
  2. 测试这三种初始化的执行顺序:
public class BeanInit implements InitializingBean {

    @PostConstruct
    public void init1() {
        System.out.println("PostConstruct 初始化");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean 接口初始化");
    }

    public void init2() {
        System.out.println("@Bean注解注入指定初始化方法");
    }
}

在这里插入图片描述

  1. @PostConstructCommonAnnotationBeanPostProcessor进行解析,属于扩展功能,最先执行。
  2. InitializingBean接口第二执行。
  3. @Bean的initMethod属性在ConfigurationClassPostProcessor解析BeanDefinetion时才会执行。
  4. 销毁方法也有三种方式:@PreDestroy、实现DisposableBean接口、@Bean指定destroyMethod方法。
public class BeanDestroy implements DisposableBean {
    @PreDestroy
    public void destroy1() {
        System.out.println("@PreDestroy进行销毁");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean接口销毁");
    }

    public void destroy2() {
        System.out.println("@Bean执行的销毁");
    }
}

在这里插入图片描述

单例中注入多例bean问题

  1. 在一个单例中注入一个多例bean。
/**
 * 在单例中注入多例bean
 */
@Configuration
@ComponentScan("scope")
public class ScopeApplicationTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScopeApplicationTest.class);
        ScopeBean scopeBean = applicationContext.getBean(ScopeBean.class);
        System.out.println(scopeBean);

        System.out.println(scopeBean.getPropertyBean());
        System.out.println(scopeBean.getPropertyBean());
        System.out.println(scopeBean.getPropertyBean());
    }
}
/**
 * 默认单例
 */
@Component
public class ScopeBean {
    /**
     * 注入一个多例的bean
     */
    @Autowired
    private PropertyBean propertyBean;

    public PropertyBean getPropertyBean() {
        return propertyBean;
    }
}
/**
 * 指定为多例bean
 */
@Scope("prototype")
@Component
public class PropertyBean {
}
  1. 预测输出多个实例,但是注入的多例,输出后还是单例。

在这里插入图片描述

  1. 对于单例对象来讲,依赖注入只发生一次,后续创建的多例没有在使用到,因此始终使用的第一次依赖注入的对象。
  2. 解决方法一:加上@Lazy注解,生成多例的代理对象。代理对象虽然是同一个,但是每次使用代理对象的任意方法时,由代理对象生成一个新的对象。
/**
 * 默认单例
 */
@Component
public class ScopeBean {
    /**
     * 注入一个多例的bean
     */
    @Lazy
    @Autowired
    private PropertyBean propertyBean;

    public PropertyBean getPropertyBean() {
        return propertyBean;
    }
}
  1. 解决方法二:在@Scoper注解上添加代理配置
/**
 * 指定为多例bean
 */
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
@Component
public class PropertyBean {
}
  1. 解决方法三:注入一个ObjectFactory工厂。
/**
 * 默认单例
 */
@Component
public class ScopeBean {
    /**
     * 注入一个多例的bean
     */
    @Autowired
    private ObjectFactory<PropertyBean> propertyBean;

    public PropertyBean getPropertyBean() {
        return propertyBean.getObject();
    }
}
  1. 解决方法四:从applicationContext容器中获取。
/**
 * 默认单例
 */
@Component
public class ScopeBean {
    /**
     * 注入一个多例的bean
     */
    @Autowired
    private ApplicationContext applicationContext;

    public PropertyBean getPropertyBean() {
        return applicationContext.getBean(PropertyBean.class);
    }
}

Spring容器启动流程

  1. 使用AnnotationConfigApplicationContext容器进行测试,类图如下。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值