Spring 中的几个常用的钩子接口
1.Aware接口
Awear 这个单词的意思是知道的,所以可以猜想以Awear 结尾的接口意思可以把他知道的东西告诉我们。常用的Awear接口有 ApplicationContextAware和 BeanFactoryAware,另外还有BeanNameAware 和EnvironmentAware
(1)ApplicationContextAware 接口 可以返回 ApplicationContext,也就是容器本身,我们可以通过ApplicationContext 这个容器对象做很多事,最常见的是获取Bean,和判断当前容器是否包含某个组件。下面的示例是通过ApplicationContext 获取Bean的示例(工程基于SpringBoot2.2.1.RELEASE)
package com.spring.hook.compent; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; /** * @Author lizhilong * @create 2019/11/28 13:51 * @desc */ @Component public class SpringContextAware implements ApplicationContextAware { private static ApplicationContext app; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { app = applicationContext; } public static<T> T getBeanByClass(Class<T> clazz){ return app.getBean(clazz); } public static Class<?> getBeanByType(String type){ return app.getType(type); } @SuppressWarnings("unchecked") public static <T> T getBeanByName(String name){ return (T) app.getBean(name); } }
(2)BeanFactoryAware 。通过实现 BeanFactoryAware 可以获取BeanFactory。Beanfactory 作用和ApplicationContext 类似,BeanFactory 比ApplicationContext更底层一些, 当然功能更加单一一些,ApplicationContext 在此基础做了一些加强,比如多了国际化等一些信息。
package com.spring.hook.compent; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.stereotype.Component; /** * @Author lizhilong * @create 2019/11/28 16:48 * @desc */ @Component public class BeanFactoryContext implements BeanFactoryAware{ private static BeanFactory beanFactory; @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { BeanFactoryContext.beanFactory = beanFactory; } public static<T> T getBeanByClass(Class<T> clazz){ return beanFactory.getBean(clazz); } }
(3)BeanNameAware。这个接口个人感觉作用不明显,通过实现这个接口可以获取当前Bean的名称。
package com.spring.hook.compent; import org.springframework.beans.factory.BeanNameAware; import org.springframework.stereotype.Component; /** * @Author lizhilong * @create 2019/11/28 14:19 * @desc */ @Component public class Car implements BeanNameAware{ @Override public void setBeanName(String s) { System.out.println("BeanName:"+s); } private String brand; private String color; public String getCarAttr(){ return "品牌:"+brand+" 颜色:"+color; } public void setBrand(String brand) { this.brand = brand; } public void setColor(String color) { this.color = color; } }
(4)EnvironmentAware 通过实现这个接口可以获取当前运行环境的一些信息。
package com.spring.hook.compent; import org.springframework.context.EnvironmentAware; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; /** * @Author lizhilong * @create 2019/11/28 17:25 * @desc */ @Component public class EnvironmentContext implements EnvironmentAware { @Override public void setEnvironment(Environment environment) { String[] activeProfile = environment.getActiveProfiles(); String[] defaultProfile = environment.getDefaultProfiles(); String port = environment.getProperty("dog.type"); } }
2.InitializingBean,DisposableBean 通过实现这两个接口可以在Bean初始化后和摧毁钱做一些事。InitializingBean 接口的afterPropertiesSet() 方法在set属性完成后执行,DisposableBean 的 destroy() 方法在bean摧毁前BeanFactory执行
package com.spring.hook.compent; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Component; /** * @Author lizhilong * @create 2019/11/28 17:45 * @desc */ @Component public class Fruit implements InitializingBean,DisposableBean{ @Override public void destroy() throws Exception { System.out.println("我要被销毁了"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("我原来的名字叫:"+name); name = "苹果"; } private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
3.PostProcessor 这个接口被称为后置处理器,常见的有:BeanPostProcessor,BeanFactoryPostProcessor ,分别为Bean的后置处理器和BeanFactory的后置处理器。
(1)BeanPostProcessor 能再Bean的初始化前后做一些事,但是个人感觉很功能很单一,无法返回具体的Bean
package com.spring.hook.compent; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; /** * @Author lizhilong * @create 2019/11/28 18:19 * @desc */ @Component public class BeanPostProcessorImpl implements BeanPostProcessor{ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("初始化前BeanName:"+beanName); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("初始化后BeanName:"+beanName); return bean; } }
(2)BeanFactoryPostProcessor
package com.spring.hook.compent; import org.springframework.beans.BeansException; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.stereotype.Component; /** * @Author lizhilong * @create 2019/11/28 18:29 * @desc */ @Component public class BeanPostFactoryContextImpl implements BeanFactoryPostProcessor { private static ConfigurableListableBeanFactory beanFactory; @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { beanFactory = configurableListableBeanFactory; if(beanFactory.containsBean("fruit")){ BeanDefinition fruit = beanFactory.getBeanDefinition("fruit"); MutablePropertyValues propertyValues = fruit.getPropertyValues(); propertyValues.add("name","香蕉"); } Fruit fruit = (Fruit)beanFactory.getBean("fruit"); System.out.println("我现在的名字叫:"+fruit.getName()); } }
示例中我们在不同的时刻为 Fruit 的name属性赋值,运行结果:
我原来的名字叫:香蕉
我现在的名字叫:苹果