码迷,mamicode.com
首页 > 编程语言 > 详细

003-Spring4 扩展分析BeanPostProcessor、BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor

时间:2018-01-21 17:41:36      阅读:533      评论:0      收藏:0      [点我收藏+]

标签:对象   generic   conf   nmon   lin   一个   contex   system   package   

一、依赖注入ApplicationContext

方法一、@Autowired

创建一个User,内部使用ApplicationContext

技术分享图片
@Component
public class User {
    @Autowired
    private ApplicationContext applicationContext;
    public void show() {
        System.out.println("User:"+applicationContext.getClass());
    }
}
View Code

使用

技术分享图片
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.lhx.spring.kuozhan");
        System.out.println(context.getBean("user"));
//        System.out.println(context.getBean("createUser"));
        User bean = (User) context.getBean("user");
        bean.show();
        context.close();
    }
View Code

方法二、实现ApplicationContextAware接口

技术分享图片
@Component
public class Book implements ApplicationContextAware{
    private ApplicationContext ApplicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.ApplicationContext=applicationContext;
    }

    public void show() {
        System.out.println("book:"+ApplicationContext.getClass());
    }
}
View Code

1)内部原理

接口BeanPostProcessor,内部方法,每一个bean初始化都会被执行

  bean初始化属性完毕后,即依赖装配完成之后,postProcessBeforeInitialization

  bean初始化在属性设置之后,Bean init之后触发的,postProcessAfterInitialization

  作用:回调,返回代理对象等

  如在postProcessBeforeInitialization中返回其他代理对象。

构建一个默认实现【两个方法不能返回null】

技术分享图片
package com.lhx.spring.kuozhan;

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

@Component
public class EchoBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("--------------postProcessBeforeInitialization-------------" + "bean" + bean.getClass());
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("--------------postProcessBeforeInitialization-------------" + "bean" + bean.getClass());
        return bean;
    }

}
View Code

2)示例

User类

技术分享图片
@Component
public class User {
    private ApplicationContext applicationContext;

    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public void init() {
        System.out.println("User init");

    }

    public void show() {
        System.out.println("User:" + applicationContext.getClass());
    }
}
View Code

UserConfig类

技术分享图片
@Configuration
public class MyConfig {
    @Bean(initMethod = "init")
    public User createUser() {
        return new User();
    }
}
View Code

调用

System.out.println(context.getBean("user"));

查看日志

User Set属性
--------------postProcessBeforeInitialization-------------beanclass com.lhx.spring.kuozhan.User
User init
--------------postProcessAfterInitialization-------------beanclass com.lhx.spring.kuozhan.User

3)自行实现ApplicationContextAware,这里起名为SpringContextAware,逻辑参考ApplicationContextAwareProcessor 

技术分享图片
public interface SpringContextAware {
    public void setApplicationContext(ApplicationContext applicationContext);
}
View Code

编写ContextBeanPostProcessor

技术分享图片
package com.lhx.spring.kuozhan;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class ContextBeanPostProcessor implements BeanPostProcessor {
    @Autowired
    private ApplicationContext applicationContext;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof SpringContextAware) {
            SpringContextAware sca = (SpringContextAware) bean;
            sca.setApplicationContext(applicationContext);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // TODO Auto-generated method stub
        return bean;
    }

}
View Code

实际类使用

技术分享图片
package com.lhx.spring.kuozhan;

import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class Dog implements SpringContextAware {

    private ApplicationContext applicationContext;

    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }


    public void show() {
        System.out.println("Dog:" + applicationContext.getClass());
    }
}
View Code

使用:

context.getBean(Dog.class).show();

4)查看ApplicationContextAware内部实现:

AnnotationConfigApplicationContext→GenericApplicationContext→AbstractApplicationContext

找打refresh方法,prepareBeanFactory,

// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

ApplicationContextAwareProcessor内部

class ApplicationContextAwareProcessor implements BeanPostProcessor 

技术分享图片

 

方法三、Spring 4.3 新特性,构造方法直接添加,有局限性,与构造方法直接相关

技术分享图片
@Component
public class Bank {
    private ApplicationContext applicationContext;
    //spring 4.3 提供,与构造方法调用有关
    public Bank(ApplicationContext applicationContext) {
        this.applicationContext=applicationContext;
    }
    public void show() {
        System.out.println("book:"+applicationContext.getClass());
    }
}
View Code

 二、容器扩展

2.1、BeanFactoryPostProcessor

在beanFactory之后,BeanFactoryPostProcessor容器初始化之后,只初始化一次,先于所有容器以及BeanPostProcessor

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

示例代码扩展2

源码:

AnnotationConfigApplicationContext→GenericApplicationContext→AbstractApplicationContext

找打refresh方法

技术分享图片
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset ‘active‘ flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring‘s core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }
View Code

2.2、BeanDefinitionRegistryPostProcessor

BeanFactoryPostProcessor的子类BeanDefinitionRegistryPostProcessor

void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

注册一个Bean到Spring容器中,类似标注了@Componment

示例

新建一个Person类

技术分享图片
public class Person {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + "]";
    }

}
View Code

MyBeanDefinitionRegistryPostProcessor实现

技术分享图片
package com.lhx.spring.kuozhan2;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // TODO Auto-generated method stub

    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        for (int i = 0; i < 10; i++) {
            BeanDefinitionBuilder rootBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
            rootBeanDefinition.addPropertyValue("name", "admin" + i);
            registry.registerBeanDefinition("person" + i, rootBeanDefinition.getBeanDefinition());
        }

    }

}
View Code

使用

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.lhx.spring.kuozhan2");
        System.out.println(context.getBean("person1"));
        context.getBeansOfType(Person.class).values().forEach(System.out::println);
        context.close();
    }

当然在使用

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.lhx.spring.kuozhan2");

使用context也可以注入

context.registerBeanDefinition(beanName, beanDefinition);
beanDefinition定义可以使用:BeanDefinitionBuilder rootBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class);

  代码地址:https://github.com/bjlhx15/spring-boot.git

003-Spring4 扩展分析BeanPostProcessor、BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor

标签:对象   generic   conf   nmon   lin   一个   contex   system   package   

原文地址:https://www.cnblogs.com/bjlhx/p/8324409.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!