spring 详解三 IOC(spring实例化及后处理器)

Spring实例化基本流程

Spring在容器初始化的时候,读取XMl配置,将其封装成BeanDefinition(Bean定义)对象,描述所有bean的信息

BeanDefinition会注册存储到beanDefinitionMap集合中

Spring框架遍历beanDefinitionMap,使用反射创建Bean实例对象

创建好之后的对象存储在singletonObjects的map集合中,当getBean时,从该map中取出实例bean对象返回

Spring配置文件中的配置项都能在BeanDefinition对象中找到 

BeanDefinition是一个接口,我们使用RootBeanDefinition即可

 Spring中的两个后处理器

Spring中提供两个后处理器,让我们能够介入实例化流程,动态注册BeanDefinition,动态修改BeanDefinition,以及动态修改Bean的作用

BeanFactoryPostProcessor:Bean工厂后处理器,在beanDefinitionMap填充完毕,还未反射创建对象之前执行

BeanPostProcessor:Bean后处理器 ,在Bean实例化之后,填充至singletonObjects之前执行,一但添加至singletonObjects意味着不能改变,有一个before和after,中间隔着初始化方法的执行。

一个在还未创建对象之前,一个在创建对象之后

Bean工厂后处理器 BeanFactoryPostProcessor

BeanFactoryPostProcessor是一个接口,实现了该接口的类只要交由spring容器管理的话,那么spring就会回调该接口的方法,用于对BeanDefinition注册和修改

package com.tech.test.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;

public class MyBeanFactoryProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("BeanDefinitionMap填充完毕之后执行该方法");
        // 创建一个BeanDefinition 
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
        rootBeanDefinition.setBeanClassName("com.tech.test.test.bean.DI");
        // 查看继承关系图ConfigurableListableBeanFactory就是DefaultListableBeanFactory
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
        // 注册Bean
        defaultListableBeanFactory.registerBeanDefinition("userService",rootBeanDefinition);
        
    }
}
 <bean id="userService"  name="aaa,bbb"  class="com.tech.test.service.impl.UserServiceImpl" ></bean>
<bean  class="com.tech.test.processor.MyBeanFactoryProcessor "></bean>

需要在配置文件中配置交给spring管理,这个示例 我们动态的修改对象userService为DI对象,当我们getBean时,Bean已经被修改为DI对象

spring提供了专门注册BeanDefinitionMap的接口,BeanDefinitionRegistryPostProcessor,看下继承关系,它是BeanFactoryPostProcessor 的子接口

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.beans.factory.support;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}

演示相同功能 

package com.tech.test.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;

public class MyNoCastProcessor implements BeanDefinitionRegistryPostProcessor {

    // 执行顺序早于postProcessBeanFactory 简记为 谁在上边谁先执行
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        // 创建一个BeanDefinition
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
        rootBeanDefinition.setBeanClassName("com.tech.test.test.bean.DI");
        // 注册Bean
        beanDefinitionRegistry.registerBeanDefinition("userService",rootBeanDefinition);
    }

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

    }
}
<bean id="userService"  name="aaa,bbb"  class="com.tech.test.service.impl.UserServiceImpl" ></bean>

<bean id="process" class="com.tech.test.processor.MyNoCastProcessor"></bean>

示例:定义自定义注解实现注册对象,配置就不列举啦,需要在对象未创建之前加入Bean定义信息

自定义注解

package com.tech.test.anotation;

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

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyComponent {

    String value();
}

 加上注解

package com.tech.test.testbean;


import com.tech.test.anotation.MyComponent;

@MyComponent("ceshi")
public class TestAnnotation {
}

 解析注解

package com.tech.test.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;

public class ParseMyComponentProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        // 这里的全限定类名和注解中的名称应该扫描包得到,这里暂时写死
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
        rootBeanDefinition.setBeanClassName("com.tech.test.testbean.TestAnnotation");
        beanDefinitionRegistry.registerBeanDefinition("ceshi",rootBeanDefinition);
    }

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

    }
}

 测试注解

package com.tech.test.springtest;

import com.tech.test.testbean.DI;
import com.tech.test.testbean.TestAnnotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestParseAnnotation {

    public static void main(String[] args) {
        // 创建ApplicationContext,加载配置文件,实例化容器
        ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取Bean
        TestAnnotation testAnnotation = classPathXmlApplicationContext.getBean(TestAnnotation.class);

        System.out.println(testAnnotation);
    }
}

Bean后处理器BeanPostProcessor

Bean后处理器 ,在Bean实例化之后,填充至singletonObjects之前执行,一但添加至singletonObjects意味着不能改变

 示例:为spring中的Bean执行方法添加时间,执行开始之前加入时间,执行之后加入时间,这里使用jdk动态代理做增强

package com.tech.test.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import java.lang.reflect.Proxy;
import java.util.Date;

public class MyBeanProcessor implements BeanPostProcessor {

    // before 和after之间隔着InitliazeBean初始化的执行过程

      @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }


    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        Object proxyBean = Proxy.newProxyInstance(
                bean.getClass().getClassLoader(),
                bean.getClass().getInterfaces(),
                (proxy, method, args) -> {
                    System.out.println("方法" + method.getName() + "开始时间" + new Date());

                    // 执行目标方法
                    Object invoke = method.invoke(bean, args);

                    System.out.println("方法" + method.getName() + "结束时间" + new Date());
                    return invoke;
        });
        return proxyBean;
    }
}
<bean  class="com.tech.test.processor.MyBeanProcessor"></bean>

测试结果

package com.tech.test.springtest;

import com.tech.test.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestApplicationContext {
    public static void main(String[] args) {

        ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

        UserService userService =(UserService) classPathXmlApplicationContext.getBean("userService");


        userService.getUser();

    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值