爱收集资源网

闲鱼搜索应用 SWAK 框架:解决代码耦合与业务拆解难题

爱收集资源网 2024-09-28 11:31

在编程领域,实现搜索功能经常成为棘手的问题。每当开启搜索模式,必须对不同搜索类别进行判别并呈现多样化页面布局。看似简单,实际编写中代码极易变得混乱。若所有代码集于一点,维护工作将如噩梦般难以应对。

SWAK的诞生:解救被耦合困扰的代码

SWAK问世旨在攻克这一棘手难题。其功能是将所有if-else语句扁平化,以TAG形式进行路由处理。这使代码结构变得顺畅,并提升了搜索的灵活性。尽管代码量不大,却囊括了SWAK的关键流程,显著简化了我们的工作。

核心问题:SWAK如何找到对应的接口实现

if(搜商品) {
if(搜商品A版本) {
doSomething1();
}else if(搜商品B版本) {
doSomething2();
}
} else if(搜会玩) {
doSomething3();
} else if(搜用户) {
if(搜用户A版本) {
doSomething4();
}else if(搜用户B版本) {
doSomething5();
}
}

SWAK的关键在于识别适当的接口实现。此问题可细分为注册与执行两环节。注册阶段,对象不应直接纳入Spring容器,而须转换为代理。此举允许按需生成不同的@SwakTag实例,达成动态的替换机制。

Spring的助力:Bean的注册与Hook

/**
* 1.首先先定义一个接口
*/
@SwakInterface(desc = "组件解析") // 使用注解声明这是一个多实现接口
public interface IPage {
SearchPage parse(Object data);
}

/**
* 2.然后编写相应的实现,这个实现可以有很多个,用TAG进行标识
*/
@Component
@SwakTag(tags = {ComponentTypeTag.COMMON_SEARCH})
public class CommonSearchPage implements IPage {
@Override
public SearchPage parse(Object data) {
return null;
}
}

/**
* 3.编写Swak路由的入口
*/
@Component
public class PageService {
@Autowired
private IPage iPage;

@SwakSessionAop(tagGroupParserClass = PageTypeParser.class,
instanceClass = String.class)
public SearchPage getPage(String pageType, Object data) {
return iPage.parse(data);
}
}

/**
* 4.编写相应的解析类
*/
public class PageTypeParser implements SwakTagGroupParser {
@Override
public SwakTagGroup parse(String pageType) {
// pageType = ComponentTypeTag.COMMON_SEARCH
return new SwakTagGroup.Builder().buildByTags(pageType);
}
}

Spring已预先配置了该接口。在Bean注册流程中,Spring将检索所有实现BeanDefinitionRegistryPostProcessor接口的Bean,并触发其postProcessBeanDefinitionRegistry方法。通过继承此接口并自定义方法,我们能够干预此流程,从而提高代码的灵活性。

操作阶段的奥秘:SwakSessionAop与SwakTagGroupParser技术

执行阶段,核心宗旨为:利用SwakTagGroupParser解析@SwakSessionAop标注的函数前的参数,识别IPage成员变量所指的CommonSearchPage实现类。此后,函数体内ipage.parse()的调用将直接映射至CommonSearchPage的parse()。此过程宛若魔法般神秘。

切面与代理:让代码更加智能

通过@Around注解,于方法启动时实施切面以运行代码。首先应用SwakTagGroupParser解析tagGroup,并将解析结果保存,随后通过调用jointPoint.proceed()维持方法流程。此流程确保方法中使用的iPage利用相关实现,提升代码智能化水平。

动态代理的妙用:intercept()方法的秘密

    public Set>> getSwakInterface() {
Reflections reflections = new Reflections(new ConfigurationBuilder()
.addUrls(ClasspathHelper.forPackage(this.packagePath))
.setScanners(new TypeAnnotationsScanner(), new SubTypesScanner())
);
return reflections.getTypesAnnotatedWith(SwakInterface.class);
}

回溯至之前,我们对标注为@SwakInterface的类在注册阶段增设了动态代理机制。因此,针对iPage的引用在进行方法调用前,需先行执行所提及的intercept()方法。该方法利用保存的tagGroup定位到所需调用的SwakTag,进而获取对应实现类的实例,并通过method.invoke()执行其实例的方法调用。这些操作显著提升了代码的灵活性。

SWAK的魅力:让代码不再纠结,搜索更自由!

SWAK的独特之处在于其解放代码的束缚,赋予搜索功能极高的自由度。借助SWAK,复杂的搜索逻辑得以拆解为独立标签,并由路由系统进行高效管理。因此,代码维护变得更加便捷,搜索功能的实施亦更为灵活。

@Configuration
public class ProxyBeanDefinitionRegister implements BeanDefinitionRegistryPostProcessor {

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
Set<Class> typesAnnotatedWith = getSwakInterface();

for (Class superClass : typesAnnotatedWith) {
if (!superClass.isInterface()) {
continue;
}

RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(SwakInterfaceProxyFactoryBean.class);

beanDefinition.getPropertyValues().addPropertyValue("swakInterfaceClass", superClass);
String beanName = superClass.getName();
beanDefinition.setPrimary(true);
beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
}
}
}

总结:SWAK让编程变得更加有趣

SWAK使编程更具趣味。该工具不仅缓解了代码耦合难题,还显著提升了搜索功能的灵活性和自主性。借助SWAK,我们得以流畅掌握复杂搜索逻辑,令代码更具智能与弹性。这些改进显著增强了编程工作的趣味性与挑战性。

public class SwakInterfaceProxyFactoryBean implements FactoryBean {
@Override
public Object getObject() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this);
this.clazz = clazz;
// 这里一般不用new出来,可以把SwakInterfaceProxy也交给Spring进行托管,这里为了表述清晰用new指代一下
enhancer.setCallback(new SwakInterfaceProxy());
// 返回代理对象,返回的对象起始就是一个封装了"实体类"的代理类,是实现类的实例。
return enhancer.create();
}
}

结尾:你准备好迎接SWAK的挑战了吗?

您已洞悉SWAK的吸引力及其运作机制。是否已踏入SWAK的挑战门槛?意欲借助SWAK提升代码的搜索自由度与灵活性?欢迎在评论区交流看法与实操,共同揭示SWAK的无限潜力!

闲鱼业务网
相关文章