Spring框架中常用的技巧及扩展点

Spring框架中常用的技巧及扩展点

首页角色扮演代号RIVER更新时间:2024-07-02

Spring是现在非常流行的轻量级Java开发框架,简化Java开发,提供了丰富的功能,工作中基本都会使用到它,如框架整合;总结下spring中常用的使用技巧及扩展点。

1、ApplicationContextAware、EnvironmentAware

ApplicationContextAware接口定义如下:

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、DisposableBean

InitializingBean接口定义如下:

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、SmartLifecycle

Lifecycle接口定义如下:

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