Spring是现在非常流行的轻量级Java开发框架,简化Java开发,提供了丰富的功能,工作中基本都会使用到它,如框架整合;总结下spring中常用的使用技巧及扩展点。
1、ApplicationContextAware、EnvironmentAwareApplicationContextAware接口定义如下:
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws beansException;
}
当一个类实现了ApplicationContextAware接口之后,这个类就可以方便获得ApplicationContext中的所有bean;
我们可以新建工具类,实现该接口,方便获取Spring容器中的bean。
@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接口定义如下:
public interface EnvironmentAware extends Aware {
void setEnvironment(Environment environment);
}
实现了EnvironmentAware接口重写setEnvironment方法后,在项目启动时可以获得application.properties的配置文件的属性值。
我们可以写一个获取属性的工具类,这里我们使用EnvironmentAware的实现类PropertySourcesPlaceholderConfigurer,工具类继承PropertySourcesPlaceholderConfigurer;
代码如下:
@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后置处理器,接口定义如下:
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的过程。
@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、DisposableBeanInitializingBean接口定义如下:
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
DisposableBean接口定义如下:
public interface DisposableBean {
void destroy() throws Exception;
}
如果Bean对象实现了InitializingBean接口,就调用其afterPropertiesSet()方法,初始化bean中的参数,或者校验参数;
InitializingBean执行在BeanPostProcessor的两个方法之间,顺序为:postProcessBeforeInitialization -> initializingBean -> postProcessAfterInitialization
如果Bean对象实现了DisposableBean接口,当容器关闭时回调destroy方式执行销毁逻辑。
@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在关闭容器时调用;
@Service
public class AService {
@PostConstruct
public void init() {
System.out.println("执行初始化逻辑");
}
@PreDestroy
public void d() {
System.out.println("容器关闭时逻辑");
}
}
5、BeanFactoryPostProcessor
bean工厂后置处理器,该接口定义如下:
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
BeanFactoryPostProcessor表示Bean工厂的后置处理器,其实和BeanPostProcessor类似,
BeanPostProcessor是干涉Bean的创建过程,BeanFactoryPostProcessor是干涉BeanFactory的创建过程。
如下代码,自定义RiverBeanFactoryPostProcessor,修改bean定义由单例改为原型。
@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");
}
}
测试代码:
@Component
public class OrderService {
}
@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
该接口定义如下:
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
该接口继承自BeanFactoryPostProcessor,具有BeanFactoryPostProcessor的功能,还兼具BeanDefinition注册的功能。
通过实现BeanDefinitionRegistryPostProcessor,可以将一个类注册为BeanDefinition,
这样不需要在类上加@Component注解,就可以从spring容器中获取该bean对象。
@Component
public class RiverBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("postProcessBeanDefinitionRegistry...");
// 生成OrderService的bean定义
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
该接口定义如下:
public interface ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}
ImportBeanDefinitionRegistrar接口是也是spring的扩展点之一,它支持自定义BeanDefinition对象;
ImportBeanDefinitionRegistrar类只能通过其他类@Import的方式来加载,通常是启动类或配置类。
实现此接口的类会回调registerBeanDefinitions方法,将类注册到spring容器中。
public class RiverServiceRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
//指定bean定义信息
rootBeanDefinition rootBeanDefinition = new RootBeanDefinition(UserService.class);
//注册一个bean指定bean名字
beanDefinitionRegistry.registerBeanDefinition("userService", rootBeanDefinition);
}
}
public class UserService {
}
@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、SmartLifecycleLifecycle接口定义如下:
public interface Lifecycle {
void start();
void stop();
boolean isRunning();
}
Lifecycle常用来管理一个组件的启动和停止;
Lifecycle表示的是ApplicationContext的生命周期,可以定义一个SmartLifecycle来监听ApplicationContext的启动和关闭。
@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;
}
}
测试:
@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逻辑的扩展点。
接口定义如下:
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。
@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;
}
}
public class UserBean {
}
测试:
@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接口定义如下:
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}
如果容器中有一个ApplicationListener的Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener的Bean将自动被触发。
Spring中有一些内置的事件,当完成摸个动作时会触发某些事件,如ContextRefreshedEvent事件,当所有的bean都初始化完成并被成功装载后会触发该事件,实现ApplicationListener接口可以收到监听动作。
我们也可以自定义事件监听,来完成某些业务逻辑。
@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
public class MsgEvent extends ApplicationEvent {
public MsgEvent(Object source) {
super(source);
}
}
测试代码:
@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);
}
}
原文链接:https://river106.cn/posts/b45c4f72.html
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved