Spring是现在非常流行的轻量级Java开发框架,简化Java开发,提供了丰富的功能,工作中基本都会使用到它,如框架整合;总结下Spring中常用的使用技巧及扩展点。
1、ApplicationContextAware、EnvironmentAware
ApplicationContextAware接口定义如下:
1 2 3 4 5
| public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
|
当一个类实现了ApplicationContextAware接口之后,这个类就可以方便获得ApplicationContext中的所有bean;
我们可以新建工具类,实现该接口,方便获取Spring容器中的bean。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Component public class ApplicationContextUtils implements ApplicationContextAware {
private static ApplicationContext context;
@Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { context = applicationContext; }
public static ApplicationContext getApplicationContext() { return context; }
public static Object getBean(String beanName) { if(context != null) { return context.getBean(beanName); } return null; }
}
|
EnvironmentAware接口定义如下:
1 2 3 4
| public interface EnvironmentAware extends Aware { void setEnvironment(Environment environment); }
|
实现了EnvironmentAware接口重写setEnvironment方法后,在项目启动时可以获得application.properties的配置文件的属性值。
我们可以写一个获取属性的工具类,这里我们使用EnvironmentAware的实现类PropertySourcesPlaceholderConfigurer,工具类继承PropertySourcesPlaceholderConfigurer;
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Component public class EnvUtils extends PropertySourcesPlaceholderConfigurer {
private static ConfigurableEnvironment ENV;
@Override public void setEnvironment(Environment environment) { super.setEnvironment(environment); if (environment instanceof ConfigurableEnvironment) { ENV = (ConfigurableEnvironment) environment; } else { ENV = new StandardEnvironment(); } }
public static String getProperty(String key) { return ENV.getProperty(key); }
}
|
2、BeanPostProcessor
bean后置处理器,接口定义如下:
1 2 3 4 5 6 7 8 9 10 11
| public interface BeanPostProcessor {
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; }
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; }
}
|
一个BeanPostProcessor可以在任意一个Bean的初始化之前以及初始化之后去额外的做一些用户自定义的逻辑,
当然,我们可以通过判断beanName来进行针对性处理(针对某个Bean,或某部分 Bean),
可以通过定义BeanPostProcessor来干涉Spring创建Bean的过程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Component public class RiverBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if(Objects.equals(beanName, "userService")) { System.out.println("userService初始化前"); } return bean; }
@Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if(Objects.equals(beanName, "userService")) { System.out.println("userService初始化后"); } return bean; } }
|
Spring中的AOP就是基于初始化后实现的,初始化后返回的对象才是最终的Bean对象。
3、InitializingBean、DisposableBean
InitializingBean接口定义如下:
1 2 3 4 5
| public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
|
DisposableBean接口定义如下:
1 2 3 4
| public interface DisposableBean {
void destroy() throws Exception; }
|
如果Bean对象实现了InitializingBean接口,就调用其afterPropertiesSet()方法,初始化bean中的参数,或者校验参数;
InitializingBean执行在BeanPostProcessor的两个方法之间,顺序为:postProcessBeforeInitialization -> initializingBean -> postProcessAfterInitialization
如果Bean对象实现了DisposableBean接口,当容器关闭时回调destroy方式执行销毁逻辑。
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Component public class UserBean implements InitializingBean, DisposableBean {
@Override public void afterPropertiesSet() throws Exception { System.out.println("执行初始化逻辑"); }
@Override public void destroy() throws Exception { System.out.println("执行销毁逻辑"); } }
|
4、@PostConstruct、@PreDestroy
@PostConstruct在bean创建完成并且属性赋值完成,来执行初始化方法
@PreDestroy在关闭容器时调用;
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Service public class AService {
@PostConstruct public void init() { System.out.println("执行初始化逻辑"); }
@PreDestroy public void d() { System.out.println("容器关闭时逻辑"); } }
|
5、BeanFactoryPostProcessor
bean工厂后置处理器,该接口定义如下:
1 2 3 4 5
| public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
|
BeanFactoryPostProcessor表示Bean工厂的后置处理器,其实和BeanPostProcessor类似,
BeanPostProcessor是干涉Bean的创建过程,BeanFactoryPostProcessor是干涉BeanFactory的创建过程。
如下代码,自定义RiverBeanFactoryPostProcessor,修改bean定义由单例改为原型。
1 2 3 4 5 6 7 8 9 10 11
| @Component public class RiverBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("RiverBeanFactoryPostProcessor..."); BeanDefinition beanDefinition = beanFactory.getBeanDefinition("orderService"); beanDefinition.setScope("prototype"); }
}
|
测试代码:
1 2 3
| @Component public class OrderService { }
|
1 2 3 4 5 6 7 8 9 10
| @ComponentScan("cn.river.spring") public class AppConfig {
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); System.out.println(context.getBean("orderService")); System.out.println(context.getBean("orderService")); System.out.println(context.getBean("orderService")); } }
|
6、BeanDefinitionRegistryPostProcessor
该接口定义如下:
1 2 3 4 5
| public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
|
该接口继承自BeanFactoryPostProcessor,具有BeanFactoryPostProcessor的功能,还兼具BeanDefinition注册的功能。
通过实现BeanDefinitionRegistryPostProcessor,可以将一个类注册为BeanDefinition,
这样不需要在类上加@Component注解,就可以从spring容器中获取该bean对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @Component public class RiverBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { System.out.println("postProcessBeanDefinitionRegistry..."); BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); beanDefinition.setBeanClass(OrderService.class); registry.registerBeanDefinition("orderService", beanDefinition); }
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
} }
|
7、ImportBeanDefinitionRegistrar
该接口定义如下:
1 2 3 4 5
| public interface ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}
|
ImportBeanDefinitionRegistrar接口是也是spring的扩展点之一,它支持自定义BeanDefinition对象;
ImportBeanDefinitionRegistrar类只能通过其他类@Import的方式来加载,通常是启动类或配置类。
实现此接口的类会回调registerBeanDefinitions方法,将类注册到spring容器中。
1 2 3 4 5 6 7 8 9 10
| public class RiverServiceRegistrar implements ImportBeanDefinitionRegistrar {
@Override public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) { RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(UserService.class); beanDefinitionRegistry.registerBeanDefinition("userService", rootBeanDefinition); } }
|
1 2
| public class UserService { }
|
1 2 3 4 5 6 7 8 9 10 11
| @Import({RiverServiceRegistrar.class}) public class ImportBeanDefinitionTest { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ImportBeanDefinitionTest.class); String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); for (String name : beanDefinitionNames) { System.out.println(name); } } }
|
Spring整合Mybatis时也会用到此扩展点。
8、SmartLifecycle
Lifecycle接口定义如下:
1 2 3 4 5 6
| public interface Lifecycle {
void start(); void stop(); boolean isRunning(); }
|
Lifecycle常用来管理一个组件的启动和停止;
Lifecycle表示的是ApplicationContext的生命周期,可以定义一个SmartLifecycle来监听ApplicationContext的启动和关闭。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @Component public class RiverLifecycle implements SmartLifecycle {
private volatile boolean running = false;
@Override public void start() { System.out.println("lifecycle start"); running = true; }
@Override public void stop() { System.out.println("lifecycle stop"); running = false; }
@Override public boolean isRunning() { System.out.println("lifecycle running state:" + running); return running; } }
|
测试:
1 2 3 4 5 6 7
| @ComponentScan("cn.river.spring") public class LifecycleTest { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(LifecycleTest.class); context.close(); } }
|
9、FactoryBean
FactoryBean是Spring容器实例化bean逻辑的扩展点。
接口定义如下:
1 2 3 4 5 6 7 8 9 10 11
| public interface FactoryBean<T> {
T getObject() throws Exception;
Class<?> getObjectType();
default boolean isSingleton() { return true; }
}
|
一般情况下,Spring通过反射机制利用bean的class属性指定实现类来实例化bean 。
在某些情况下,实例化bean过程比较复杂,Spring为此提供了FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化bean的逻辑。
后面又提供了@Configration和@Bean这种方式,一定程度上可以替代FactoryBean。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Component public class RiverFactoryBean implements FactoryBean {
@Override public Object getObject() throws Exception { return new UserBean(); }
@Override public Class<?> getObjectType() { return UserBean.class; }
@Override public boolean isSingleton() { return true; } }
|
1 2
| public class UserBean { }
|
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13
| @ComponentScan("cn.river.spring") public class FactoryBeanTest {
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(FactoryBeanTest.class); UserBean bean = (UserBean) context.getBean("riverFactoryBean"); System.out.println(bean); Object fb = context.getBean("&riverFactoryBean"); System.out.println(fb); }
}
|
10、ApplicationListener
ApplicationContext事件机制是观察者设计模式的实现,通过ApplicationEvent类和ApplicationListener接口,可以实现ApplicationContext事件处理。
ApplicationListener接口定义如下:
1 2 3 4
| public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event); }
|
如果容器中有一个ApplicationListener的Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener的Bean将自动被触发。
Spring中有一些内置的事件,当完成摸个动作时会触发某些事件,如ContextRefreshedEvent事件,当所有的bean都初始化完成并被成功装载后会触发该事件,实现ApplicationListener接口可以收到监听动作。
我们也可以自定义事件监听,来完成某些业务逻辑。
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Component public class MsgApplicationListener implements ApplicationListener<MsgEvent> {
@Override public void onApplicationEvent(MsgEvent event) { System.out.println(event.getSource()); }
@EventListener public void handle(MsgEvent event) { System.out.println("注解监听: " + event); } }
|
自定义事件,继承ApplicationEvent
1 2 3 4 5 6
| public class MsgEvent extends ApplicationEvent {
public MsgEvent(Object source) { super(source); } }
|
测试代码:
1 2 3 4 5 6 7 8 9
| @ComponentScan("cn.river.spring") public class ApplicationListenerDemo {
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationListenerDemo.class); MsgEvent msgEvent = new MsgEvent("发送短信"); context.publishEvent(msgEvent); } }
|