加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

spring深入-27-Spring启动constructor,@PostConstruct,afterPropertiesSet,onApplicationEvent顺序

(2017-05-11 14:21:29)
分类: 框架
spring 启动时,按照constructor,@PostConstruct,afterPropertiesSet,onApplicationEvent执行顺序

注:什么是ApplicationContext? 
它是Spring的核心,Context我们通常解释为上下文环境,但是理解成容器会更好些。 
ApplicationContext则是应用的容器。
Spring把Bean(object)放在容器中,需要用就通过get方法取出来。
ApplicationEven
是个抽象类,里面只有一个构造函数和一个长整型的timestamp。
ApplicationListener
是一个接口,里面只有一个onApplicationEvent方法。
所以自己的类在实现该接口的时候,要实装该方法。
如果在上下文中部署一个实现了ApplicationListener接口的bean,
那么每当在一个ApplicationEvent发布到 ApplicationContext时,
这个bean得到通知。其实这就是标准的Oberver设计模式。

1.例如:
@Component
public class BuildFactory implements InitializingBean, ApplicationListener<ContextRefreshedEvent>{
    @Autowired
    private BeanFactory beanFactory;

    @Autowired
    private List<Builder> builders;

    private Map<States, Builder> statesStateMachineMap = new ConcurrentHashMap<>();

    public BuildFactory() {
        System.out.println("constructor" + ":" + builders);
    }

    @PostConstruct
    public void postConstructMethod() {
        System.out.println("postConstruct" + ":" + builders);
    }

    public void run(States state, Events event) throws Exception{
        Builder builder = statesStateMachineMap.get(state);
        StateMachine<States, Events> stateMachine = builder.build(state, beanFactory);
        stateMachine.sendEvent(event);
    }

    public  StateMachine<States, Events> create(States state) throws Exception{
        Builder builder = statesStateMachineMap.get(state);
        StateMachine<States, Events> stateMachine = builder.build(state, beanFactory);
        stateMachine.getExtendedState().getVariables().put(InputObject.class, new Student(1, "haha"));
        return stateMachine;
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        statesStateMachineMap = builders.stream().collect(Collectors.toMap(Builder::getName, Function.identity()));
        System.out.println("afterPropertiesSet" + ":" + builders);
    }

    public void testAop(String a) {
        System.out.println(a + "testAop");
    }
    public void test2Aop(String a) {
        System.out.println(a + "testAop2");
    }

    public void testAround(String a) {
        System.out.println("run");
    }

    @MyAopAnno
    public void testAopAnno(Student student) {
        System.out.println(student.getId() + "-" + student.getName());
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        System.out.println("onApplicationEvent" + ":" + builders);
    }
}

2. 结果:
constructor:null
postConstruct:[com.scn7th.newStateMachine.Builder1@219f4597, com.scn7th.newStateMachine.Builder2@31be6b49]
afterPropertiesSet:[com.scn7th.newStateMachine.Builder1@219f4597, com.scn7th.newStateMachine.Builder2@31be6b49]
onApplicationEvent:[com.scn7th.newStateMachine.Builder1@219f4597, com.scn7th.newStateMachine.Builder2@31be6b49]

3.分析:
1)首先构造器被启动,此时还没有注入bean
2)postConstruct优先于afterPropertiesSet执行,这时bean属性竟然也被注入了

3)spring很多组建的初始化都放在afterPropertiesSet做。我们在做一些中间件想和spring一起启动,可以放在这里启动。Spring在设置完一个bean所有的合作者后,会检查bean是否实现了InitializingBean接口,如果实现就调用bean的afterPropertiesSet方法。

4)onApplicationEvent属于应用层的时间,最后被执行,很容易理解。onApplicationEvent会被频繁执行,需要使用它监听,需要考虑性能问题。很显然,这是观察者模式的经典应用。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有