栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spring bean创建流程+demo

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring bean创建流程+demo

Spring启动流程:
    解析启动类,得到扫描路径;遍历扫描路径下的java类文件; 如果类文件存在@Component、@Config等注解,则存入BeanDefinitionMap中,key为beanName。遍历BeanDefinitionMap,通过反射创建Bean;
Bean创建流程:

spring的一大优点就是扩展性很强,比如,在spring bean 的生命周期中,给我们预留了很多参与bean 的生命周期的方法。

大致梳理一下,有以下几种:

    自定义 org.springframework.beans.factory.config.BeanPostProcessor ,来让 spring 回调我们的方法来参与 bean的生命周期。在指定方法上加上@PostConstruct 或@PreDestroy注解来制定该方法是在初始化之后还是销毁之前调用;通过实现 InitializingBean/DisposableBean 接口来定制初始化之后/销毁之前的操作方法;通过 元素的 init-method/destroy-method属性指定初始化之后 /销毁之前调用的操作方法;

具体流程如下:

    实例化:利用构造方法来实例化得到一个对象(但是如何一个类中有多个构造方法,Spring则会进行选择,这个叫做推断构造方法);依赖注入:实例化后,Spring会判断该对象中是否存在被@Autowired注解了的属性,把这些属性找出来并由Spring进行依赖注入;Aware回调:如果实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware等接口,则执行相应的重写方法;执行BeanPostProcessor.postProcessBeforeInitialization()进行初始化前操作;执行@PostConstruct注解对应的方法进行初始化;执行重写的InitializingBean接口的afterPropertiesSet()方法进行初始化;执行BeanPostProcessor.postProcessAfterInitialization()进行初始化后操作(Spring的AOP在此方法内实现);
    如果不用进行AOP,那么该Bean就是此类的构造方法所得到的对象。
    如果需要进行AOP,那么该Bean就是通过动态代理生成一个代理对象,而不是该类本身所得到的对象。执行@PreDestroy注解对应的方法进行销毁前操作;执行重写的DisposableBean接口的destroy()方法进行销毁操作;

@Component
public class DemoController implements InitializingBean,DisposableBean {

    @Autowired
    private DemoService demoService;
    private String name = "Herbert";

    public DemoController() {
        System.out.println();
        System.out.println("constructor ");
        System.out.println( "name:" + name);
        System.out.println( "demoService:" + demoService);
        System.out.println();
    }

    @PostConstruct
    public void  postConstruct(){
        System.out.println();
        System.out.println("@PostConstrut");
        System.out.println( "name:" + name);
        System.out.println( "demoService:" + demoService);
        System.out.println();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println();
        System.out.println("afterPropertiesSet");
        System.out.println( "name:" + name);
        System.out.println( "demoService:" + demoService);
        System.out.println();
    }

    @PreDestroy
    public void  preDestroy(){
        System.out.println();
        System.out.println("@PreDestroy");
        System.out.println( "name:" + name);
        System.out.println( "demoService:" + demoService);
        System.out.println();
    }
    @Override
    public void destroy() throws Exception {
        System.out.println();
        System.out.println("destroy");
        System.out.println( "name:" + name);
        System.out.println( "demoService:" + demoService);
        System.out.println();
    }
    public void init(){
        System.out.println();
        System.out.println("init-method by xml 配置文件");
        System.out.println( "name:" + name);
        System.out.println( "demoService:" + demoService);
        System.out.println();
    }
    public void  cleanUp(){
        System.out.println();
        System.out.println("destroy-method by xml 配置文件");
        System.out.println( "name:" + name);
        System.out.println( "demoService:" + demoService);
        System.out.println();
    }
}

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof DemoController){
            System.out.println();
            System.out.println("BeanPostProcessor:" + "postProcessBeforeInitialization");
            Field field = null;
            try {
                field = bean.getClass().getDeclaredField("demoService");
                field.setAccessible(true);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
            try {
                Object o = field.get(bean);
                System.out.println( "demoService已注入:" + o);
                System.out.println();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof DemoController){
            System.out.println();
            System.out.println("BeanPostProcessor:" + "postProcessAfterInitialization");
            Field field = null;
            try {
                field = bean.getClass().getDeclaredField("demoService");
                field.setAccessible(true);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
            try {
                Object o = field.get(bean);
                System.out.println( "demoService已注入:" + o);
                System.out.println();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return bean;
    }
}
@Component
public class DemoService {

}
@SpringBootApplication
public class SpringBeanTest  {

    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(SpringBeanTest.class, args);
        applicationContext.close();
    }

}

执行结果:

代码下载地址:springbeanDomo.rar

推断构造方法:
    如果只有一个构造方法,用这个构造方法;如果存在多个构造方法,用无参的构造方法,若不存在无参的构造方法,那么Spring就会报错;如果某个构造方法上加了@Autowired注解,Spring就会用这个加了@Autowired注解的构造方法;

需要重视的是,如果Spring选择了一个有参的构造方法,Spring在调用这个有参构造方法时,需要传入参数,那这个参数是怎么来的呢?

Spring会根据入参的类型和入参的名字去Spring中找Bean对象(以单例Bean为例,Spring会从单例池那个Map中去找):

    先根据入参类型找,如果只找到一个,那就直接用来作为入参;如果根据类型找到多个,则再根据入参名字来确定唯一一个;最终如果没有找到,则会报错,无法创建当前Bean对象。
AOP的大致流程(cglib):
    生成代理类UserServiceProxy,代理类继承UserService;代理类中重写了父类的方法,比如UserService中的test()方法;代理类中还会有一个target属性,该属性的值为被代理对象(也就是通过UserService类推断构造方法实例化出来的对象,进行了依赖注入、初始化等步骤的对象)当我们从Spring容器得到UserService的Bean对象时,拿到的就是UserServiceProxy所生成的对象,也就是代理对象。

代码下载地址:springbeanDomo.rar

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/704010.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号