0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

剖析Spring中最常用的扩展点(下)

jf_78858299 来源:苏三说技术 作者:苏三说技术 2023-02-15 16:07 次阅读

7.修改BeanDefinition

Spring IOC在实例化Bean对象之前,需要先读取Bean的相关属性,保存到BeanDefinition对象中,然后通过BeanDefinition对象,实例化Bean对象。

如果想修改BeanDefinition对象中的属性,该怎么办呢?

答:我们可以实现BeanFactoryPostProcessor接口

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
        beanDefinitionBuilder.addPropertyValue("id", 123);
        beanDefinitionBuilder.addPropertyValue("name", "苏三说技术");
        defaultListableBeanFactory.registerBeanDefinition("user", beanDefinitionBuilder.getBeanDefinition());
    }
}

在postProcessBeanFactory方法中,可以获取BeanDefinition的相关对象,并且修改该对象的属性。

8.初始化Bean前后

有时,你想在初始化Bean前后,实现一些自己的逻辑。

这时可以实现:BeanPostProcessor接口。

该接口目前有两个方法:

  • postProcessBeforeInitialization 该在初始化方法之前调用。
  • postProcessAfterInitialization 该方法再初始化方法之后调用。

例如:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof User) {
            ((User) bean).setUserName("苏三说技术");
        }
        return bean;
    }
}

如果spring中存在User对象,则将它的userName设置成:苏三说技术。

其实,我们经常使用的注解,比如:@Autowired、@Value、@Resource、@PostConstruct等,是通过AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor实现的。

9.初始化方法

目前spring中使用比较多的初始化bean的方法有:

  1. 使用@PostConstruct注解
  2. 实现InitializingBean接口

9.1 使用@PostConstruct注解

@Service
public class AService {
    @PostConstruct
    public void init() {
        System.out.println("===初始化===");
    }
}

在需要初始化的方法上增加@PostConstruct注解,这样就有初始化的能力。

9.2 实现InitializingBean接口

@Service
public class BService implements InitializingBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("===初始化===");
    }
}

实现InitializingBean接口,重写afterPropertiesSet方法,该方法中可以完成初始化功能。

10.关闭容器前

有时候,我们需要在关闭spring容器前,做一些额外的工作,比如:关闭资源文件等。

这时可以实现DisposableBean接口,并且重写它的destroy方法:

@Service
public class DService implements InitializingBean, DisposableBean {
 
    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean destroy");
    }
 
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean afterPropertiesSet");
    }
}

这样spring容器销毁前,会调用该destroy方法,做一些额外的工作。

通常情况下,我们会同时实现InitializingBean和DisposableBean接口,重写初始化方法和销毁方法。

11.自定义作用域

我们都知道spring默认支持的Scope只有两种:

  • singleton 单例,每次从spring容器中获取到的bean都是同一个对象。
  • prototype 多例,每次从spring容器中获取到的bean都是不同的对象。

spring web又对Scope进行了扩展,增加了:

  • RequestScope 同一次请求从spring容器中获取到的bean都是同一个对象。
  • SessionScope 同一个会话从spring容器中获取到的bean都是同一个对象。

即便如此,有些场景还是无法满足我们的要求。

比如,我们想在同一个线程中从spring容器获取到的bean都是同一个对象,该怎么办?

这就需要自定义Scope了。

第一步实现Scope接口:

public class ThreadLocalScope implements Scope {
    private static final ThreadLocal THREAD_LOCAL_SCOPE = new ThreadLocal();

    @Override
    public Object get(String name, ObjectFactory objectFactory) {
        Object value = THREAD_LOCAL_SCOPE.get();
        if (value != null) {
            return value;
        }

        Object object = objectFactory.getObject();
        THREAD_LOCAL_SCOPE.set(object);
        return object;
    }

    @Override
    public Object remove(String name) {
        THREAD_LOCAL_SCOPE.remove();
        return null;
    }

    @Override
    public void registerDestructionCallback(String name, Runnable callback) {
    }

    @Override
    public Object resolveContextualObject(String key) {
        return null;
    }

    @Override
    public String getConversationId() {
        return null;
    }
}

第二步将新定义的Scope注入到spring容器中:

@Component
public class ThreadLocalBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        beanFactory.registerScope("threadLocalScope", new ThreadLocalScope());
    }
}

第三步使用新定义的Scope:

@Scope("threadLocalScope")
@Service
public class CService {
    public void add() {
    }
}
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • spring
    +关注

    关注

    0

    文章

    340

    浏览量

    14334
  • AOP
    AOP
    +关注

    关注

    0

    文章

    40

    浏览量

    11096
  • IOC
    IOC
    +关注

    关注

    0

    文章

    28

    浏览量

    10098
收藏 人收藏

    评论

    相关推荐

    Spring框架的设计理念

    Spring作为现在最优秀的框架之一,已被广泛的使用,51CTO也曾经针对Spring框架中的hqC应用做过报道。本文将从另外一个视角试图剖析Spring框架的作者设计
    发表于 07-15 08:17

    电路中最常见到的电容使用方法

    基于电容常用功能,详细介绍各功能应用电路中最常见到的电容使用方法
    发表于 03-17 08:08

    请问射击探测器中最常用的口径是什么?

    射击探测器中最常用的口径是什么?
    发表于 04-12 06:56

    开关电源中最常用的电阻有哪些呢

    一 电阻1.开关电源中最常用的电阻有贴片电阻、插件色环电阻、压敏电阻、热敏电阻等。2.贴片电阻2.1 贴片电阻:主要按封装和功率来分,常用的有0402 1/16W; 0603 1/10W; 0805
    发表于 12-29 06:14

    单片机系统中最常用的通信协议有几种

    )、MOSI(主机输出从机输入Master Output/Slave Input)和MISO(主机输入从机输出Master Input/Slave Output)。单片机系统中最常用的通信协议有三种,分...
    发表于 02-17 07:43

    单片机系统中最常用的三种通信协议是什么?

    单片机系统中最常用的三种通信协议是什么?
    发表于 02-17 06:03

    EMC问题中最常用的手段RC滤波详细资料说明

    让我们一起来看看处理 EMC 问题中最常用的手段 -RC 滤波。本文介绍了滤波的概念,并详细说明了电阻 - 电容(RC)低通滤波器的用途和特性。
    发表于 12-25 07:08 8次下载
    EMC问题<b class='flag-5'>中最常用</b>的手段RC滤波详细资料说明

    联网应用中最常用的传感器是什么?

    环境、运动、光电/图像和健康监测传感器是物联网应用中最常用的传感器类型
    的头像 发表于 08-16 11:26 963次阅读

    Spring中最常用的11个扩展

    除此之外,我们在使用spring的过程中,有没有发现它的扩展能力非常强。由于这个优势的存在,让spring拥有强大的包容能力,让很多第三方应用能够轻松投入spring的怀抱。比如:ro
    的头像 发表于 01-11 10:31 883次阅读

    剖析Spring中最常用扩展(上)

    我们一说到spring,可能第一个想到的是 `IOC`(控制反转) 和 `AOP`(面向切面编程)。 没错,它们是spring的基石,得益于它们的优秀设计,使得spring能够从众多优秀框架中脱颖而出。
    的头像 发表于 02-15 16:06 741次阅读
    <b class='flag-5'>剖析</b><b class='flag-5'>Spring</b><b class='flag-5'>中最常用</b>的<b class='flag-5'>扩展</b><b class='flag-5'>点</b>(上)

    剖析Spring中最常用扩展(中)

    我们一说到spring,可能第一个想到的是 `IOC`(控制反转) 和 `AOP`(面向切面编程)。 没错,它们是spring的基石,得益于它们的优秀设计,使得spring能够从众多优秀框架中脱颖而出。
    的头像 发表于 02-15 16:06 500次阅读
    <b class='flag-5'>剖析</b><b class='flag-5'>Spring</b><b class='flag-5'>中最常用</b>的<b class='flag-5'>扩展</b><b class='flag-5'>点</b>(中)

    基于spring的SPI扩展机制是如何实现的?

    基本上,你一说是基于 spring 的 SPI 扩展机制,再把spring.factories文件和EnableAutoConfiguration提一,那么这个问题就答的八九不离十了
    的头像 发表于 03-07 09:17 1031次阅读

    Spring中11个最常用扩展分享1

    在使用spring的过程中,我们有没有发现它的扩展能力很强呢?由于这个优势的存在,使得spring具有很强的包容性,所以很多第三方应用或者框架可以很容易的投入到spring的怀抱中。今
    的头像 发表于 05-11 10:48 554次阅读

    Spring中11个最常用扩展分享2

    在使用spring的过程中,我们有没有发现它的扩展能力很强呢?由于这个优势的存在,使得spring具有很强的包容性,所以很多第三方应用或者框架可以很容易的投入到spring的怀抱中。今
    的头像 发表于 05-11 10:48 389次阅读

    讲一失效分析中最常用的辅助实验手段:亮点分析(EMMI)

    EMMI:Emission microscopy 。与SEM,FIB,EB等一起作为最常用的失效分析手段。
    的头像 发表于 06-12 18:21 6979次阅读
    讲一<b class='flag-5'>下</b>失效分析<b class='flag-5'>中最常用</b>的辅助实验手段:亮点分析(EMMI)