初识ProxyFactory
在Spring常用工具一文中提到,ProxyFactory
可以用来手动生成代理类,以实现对某些对象进行增强。
简单再贴一下ProxyFactory
的使用方式:
1 | public class Bean { |
当需要生成一些对象的代理类进行增强需求时,用这个工具比自己手动使用动态代理等方式创建代理类方便许多。
其实,ProxyFactory
也是Spring
AOP
的实现方式,本文将解析一下ProxyFactory
的实现方式。
在Spring常用工具一文中提到,ProxyFactory
可以用来手动生成代理类,以实现对某些对象进行增强。
简单再贴一下ProxyFactory
的使用方式:
1 | public class Bean { |
当需要生成一些对象的代理类进行增强需求时,用这个工具比自己手动使用动态代理等方式创建代理类方便许多。
其实,ProxyFactory
也是Spring
AOP
的实现方式,本文将解析一下ProxyFactory
的实现方式。
本文为翻译稿,翻译自How to Synchronize Blocks by the Value of the Object in Java
以下为翻译正文,译者英文水平有限,有些复杂语句没有直译,而是翻译成了自己理解的内容。
有时候,我们需要通过一个变量来同步一个代码块。
为了理解遇到的问题,我们假设有一个银行业务系统,系统中的转账业务在每次客户端操作时都需要做如下的操作:
CashBackService
)计算转账时的返现(cash back
)金额AccountService
)这个现金转账操作流程大概如下:
1 | public void withdrawMoney(UUID userId, int amountOfMoney) { |
当需要手动给Bean
创建代理对象时,一般情况下通过CGLib或动态代理实现,在有些情况下还需要根据对象的类型区分使用生成代理的方式,可以通过ProxyFactory
快速生成一个代理类,并支持多个切面。
1 | public class Bean { |
在Spring
中,通过一些方式获取到的Bean
可能已经被增强,即可能被代理,获取被代理的对象可能会有一些意想不到的情况发生,例如通过代理对象获取类注解时可能将会获取不到。
AopUtils
提供一些方法来判断是否为代理对象,例如AopUtils#isAopProxy
;也可以调用AopUtils#getTargetClass
获取到被代理的对象类型等等。
有些场景下,需要手动注册BeanDefinition
,可以通过BeanDefinitionBuilder
进行创建BeanDefinition
。建议通过BeanDefinitionBuilder#genericBeanDefinition
创建,因为GenericBeanDefinition
涵盖了RootBeanDefinition
和ChildBeanDefinition
的功能。
1 | BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Bean.class); |
在一些场景下,可能需要手动扫描某个路径下的类进行处理。例如MyBatis
通过扫描某个路径下的mapper接口自动生成mapper
实例。
ClassPathBeanDefinitionScanner#scan(String)
将会扫描入参路径,将其中的类解析为BeanDefinition
注册到当前容器中。
1 | BeanDefinitionRegistry registry = null; |
如果有必要,例如修改扫描到的BeanDefinition
,可以重写doScan
方法;如果不满足于addIncludeFilter
或addExcludeFilter
两类过滤器,可以重写isCandidateComponent
方法手动写条件进行过滤。
本文主要介绍Spring
中所支持的常用的扩展接口,Spring
非常庞大且已成体系,众多的开发者包括Spring
框架的开发者不可能随意改动框架原来来实现个性化的需求,所以提供了许多扩展接口,遵循开闭原则
开闭原则定义:一个软件实体。如类/模块/函都应该对扩展开放,对修改关闭。
本文将描述如何通过BeanPostProcessor
以及与其相关的技术来生成接口的实现类并自动注入bean中。实现的效果类似于Mybatis
的mapper
仅需要定义接口,而无需手动生成实现类。
阅读本文之前,请先了解学习BeanPostProcessor
、InstantiationAwareBeanPostProcessor
以及BeanDefinitionRegistryPostProcessor
,可以参考此文Spring支持的扩展接口;同时需要了解FactoryBean
与ClassPathBeanDefinitionScanner
的概念,参考Spring常用工具
为了结合实际需求,请读者设想如下场景:在对接某第三方公司时,对方提供了Http接口以供调用,如果使用常规方式,需要在代码中拼接url,然后使用诸如HttpClient
一类的工具获取结果响应。如果这样的代码散落在项目当中,将会非常影响观感,有些同学会做一些封装,为每个http接口封装一个工具方法以供调用,但是需要写很多接口及其实现类,其代码大同小异,本文就将对此场景进行封装,最终实现仅需要开发同学创建对应的接口(Interface
),无需写实现类,在调用端直接用@Autowire
注入即可调用。
本文主要是以学习为目的而并非解决实际问题,上述的场景也只是工作中很简单的一个场景,所以本文将使用两种方式来实现该需求,以记录更多有用的知识点。