设计模式之过滤器模式

目录

1.简介

2.过滤器的实现

2.1.过滤器的角色

2.2.类图

2.3.具体实现

3.过滤器模式的优点

4.过滤器模式的不足

5.适用的场景


1.简介

过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种结构型设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。说的通俗些就是把一个集合对象根据过滤条件筛选出自己想要的对象。

2.过滤器的实现

2.1.过滤器的角色

抽象过滤器角色(AbstractFilter):负责定义过滤器的实现接口,具体的实现还要具体过滤器角色去参与,客户端可以调用抽象过滤器角色中定义好的方法,将客户端的所有请求委派到具体的实现类去,从而让实现类去处理;
具体过滤器角色(ConcreteFilter):该角色负责具体筛选规则的逻辑实现,最后再返回一个过滤后的数据集合,标准的过滤器只对数据做过滤,当然也可以对集合中的数据做某项处理,再将处理后的集合返回;
被过滤的主体角色(Subject):一个软件系统中可以有一个或多个目标角色,在具体过滤器角色中会对指定感兴趣的目标进行处理,以确保后面的数据确实是我想要的。

2.2.类图

ICriteria : 抽象过滤器角色,定义了抽象接口doFilter

CCriteriaMale: 具体的过滤器角色,过滤male

CCriteriaFemale: 具体的过滤器角色,过滤female

CCriteriaEducation: 具体的过滤器角色,过滤指定学历的

CCriteriaAboveAge: 具体的过滤器角色,过滤大于某个年龄的

CCriteriaAnd:具体的过滤器角色,实现两个具体的过滤器的逻辑与

CCriteriaOr:具体的过滤器角色,实现两个具体的过滤器的逻辑或

CCriteriaAndEx:具体的过滤器角色,实现多个具体的过滤器的逻辑与

CCriteriaOrEx:具体的过滤器角色,实现多个具体的过滤器的逻辑或

CPerson: 被过滤的主体角色

注:里面用到了std::initializer_list,具体用法可参考深入理解可变参数-CSDN博客的第2章节。

2.3.具体实现

主体角色和过滤器代码如下:FilterMode.h

#ifndef _FILTER_MODE_H_
#define _FILTER_MODE_H_
#include <string>
#include <vector>
#include <algorithm>


//被过滤的实体类
class CPerson
{
public:
	explicit CPerson(const std::string& name, const std::string& sex, int age, const std::string& education)
		: m_name(name), m_sex(sex), m_age(age), m_education(education) {}
	~CPerson() {}

public:
	std::string name() const { return m_name; }
	std::string sex() const { return m_sex; }
	int age() const { return m_age; }
	std::string education() const { return m_education; }
	std::string toString() const {
		return std::string("[name:") + m_name + std::string(";sex:") + m_sex + std::string(";age:") + std::to_string(m_age)
			+ std::string(";education:") + m_education + std::string("]");
	}

private:
	std::string m_name;
	std::string m_sex;
	int         m_age;
	std::string m_education;
};

//抽象过滤器
class ICriteria {
public:
	virtual std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) = 0;
};

//具体过滤器:过滤male
class CCriteriaMale : public ICriteria
{
public:
	std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) override {
		std::vector<CPerson*> malePersons;
		for (auto& it : persons) {
			if (0 == it->sex().compare("male")) {
				malePersons.push_back(it);
			}
		}
		return malePersons;
	}
};

//具体过滤器:过滤female
class CCriteriaFemale : public ICriteria
{
public:
	std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) override {
		std::vector<CPerson*> femalePersons;
		for (auto& it : persons) {
			if (0 == it->sex().compare("female")) {
				femalePersons.push_back(it);
			}
		}
		return femalePersons;
	}
};

//具体过滤器:过滤学历
class CCriteriaEducation : public ICriteria
{
public:
	explicit CCriteriaEducation(const std::string& education) :m_education(education) {}
public:
	std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) override {
		std::vector<CPerson*> eduPersons;
		for (auto& it : persons) {
			if (0 == it->education().compare(m_education)) {
				eduPersons.push_back(it);
			}
		}
		return eduPersons;
	}

private:
	std::string m_education;
};

//具体过滤器:过滤年龄
class CCriteriaAboveAge : public ICriteria
{
public:
	explicit CCriteriaAboveAge(int age) : m_age(age) {}

public:
	std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) override {
		std::vector<CPerson*> agePersons;
		for (auto& it : persons) {
			if (it->age() > m_age) {
				agePersons.push_back(it);
			}
		}
		return agePersons;
	}
private:
	int  m_age;
};

//具体过滤器:两个过滤器的逻辑与
class CCriteriaAnd : public ICriteria
{
public:
	explicit CCriteriaAnd(ICriteria* pCriteria1, ICriteria* pCriteria2)
		: m_criteria1(pCriteria1), m_criteria2(pCriteria2) {}

public:
	std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) override {
		std::vector<CPerson*> andPersons = m_criteria1->doFilter(persons);
		return m_criteria2->doFilter(andPersons);
	}
private:
	ICriteria* m_criteria1;
	ICriteria* m_criteria2;
};

//具体过滤器:1个或多个过滤器的逻辑与
class CCriteriaAndEx : public ICriteria
{
public:
	explicit CCriteriaAndEx(std::initializer_list<ICriteria*> criteria1s)
		: m_vecCriteria(criteria1s) {}

public:
	std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) override {
		int index = 0;
		std::vector<CPerson*> andPersons;
		for (auto& it : m_vecCriteria) {
			andPersons = it->doFilter(index == 0 ? persons : andPersons);
			index++;
		}
		return andPersons;
	}
private:
	std::vector<ICriteria*> m_vecCriteria;
};

//具体过滤器:两个过滤器的逻辑或
class CCriteriaOr : public ICriteria
{
public:
	explicit CCriteriaOr(ICriteria* pCriteria1, ICriteria* pCriteria2)
		: m_criteria1(pCriteria1), m_criteria2(pCriteria2) {}

public:
	std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) override {
		std::vector<CPerson*> orPersons = m_criteria1->doFilter(persons);
		std::vector<CPerson*> orPersons1 = m_criteria2->doFilter(persons);
		for (auto& it : orPersons1) {
			if (std::find_if(orPersons.begin(), orPersons.end(),
				[=](auto& iter) {return it == iter; }) == orPersons.end()) {
				orPersons.push_back(it);
			}
		}
		return orPersons;
	}
private:
	ICriteria* m_criteria1;
	ICriteria* m_criteria2;
};

//CPerson容器包装类
class CPersonContainerWrapper
{
public:
	CPersonContainerWrapper(std::vector<CPerson*>& vecData)
		: m_vecPesons(vecData) {}
public:
	CPersonContainerWrapper& operator|(const std::vector<CPerson*>& others) {
		for (auto& it : others) {
			if (std::find_if(m_vecPesons.begin(), m_vecPesons.end(),
				[=](auto& iter) {return it == iter; }) == m_vecPesons.end()) {
				m_vecPesons.push_back(it);
			}
		}
		return *this;
	}
private:
	std::vector<CPerson*>& m_vecPesons;
};

//具体过滤器:1个或多个过滤器的逻辑或
class CCriteriaOrEx : public ICriteria
{
public:
	explicit CCriteriaOrEx(std::initializer_list<ICriteria*> criteria1s)
		: m_vecCriteria(criteria1s) {}

public:
	std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) override {
		int index = 0;
		std::vector<CPerson*> orPersons;
		CPersonContainerWrapper wapper(orPersons);

		if (m_vecCriteria.size() <= 0) {
			return persons;
		}

		orPersons = m_vecCriteria[0]->doFilter(persons);
		for (index = 1; index < m_vecCriteria.size(); index++) {
			wapper | m_vecCriteria[index]->doFilter(persons);
		}
		return orPersons;
	}
private:
	std::vector<ICriteria*> m_vecCriteria;
};

#endif

使用不同的标准(Criteria)和它们的结合来过滤CPerson对象的列表,测试代码如下:

#include "FilterMode.h"
static void printPerson(const std::string& tip, std::vector<CPerson*>& persons) {
	qDebug() << tip.data();
	for (auto& it : persons) {
		qDebug() << it->toString().data();
	}
}
void main() {
	std::vector<CPerson*> vecTemp;
	std::vector<CPerson*> vecPersons;
	vecPersons.push_back(new CPerson("liu bin", "male", 39, "benke"));
	vecPersons.push_back(new CPerson("li xiang", "female", 25, "zhuanke"));
	vecPersons.push_back(new CPerson("he nan shan", "male", 44, "boshi"));
	vecPersons.push_back(new CPerson("san ling", "female", 56, "suoshi"));
	vecPersons.push_back(new CPerson("guo dong", "male", 27, "zhuanke"));
	vecPersons.push_back(new CPerson("jing gang shan", "female", 32, "suoshi"));
	vecPersons.push_back(new CPerson("shan shan", "female", 41, "benke"));
	vecPersons.push_back(new CPerson("mei duo", "male", 10, "xiaoxue"));

	ICriteria* pMaleCriteria = new CCriteriaMale();
	ICriteria* pFemaleCriteria = new CCriteriaFemale();
	ICriteria* pAgeCriteria = new CCriteriaAboveAge(26);
	ICriteria* pEduCriteria = new CCriteriaEducation("benke");
	ICriteria* pAndCriteria = new CCriteriaAnd(pMaleCriteria, pEduCriteria);
	ICriteria* pOrCriteria = new CCriteriaOr(pFemaleCriteria, pAgeCriteria);

	ICriteria* pAndCriteriaEx = new CCriteriaAndEx({ pFemaleCriteria, pAgeCriteria, pEduCriteria });
	ICriteria* pOrCriteriaEx = new CCriteriaOrEx({ pMaleCriteria, pFemaleCriteria, pEduCriteria,pAgeCriteria });

	vecTemp = pMaleCriteria->doFilter(vecPersons);
	printPerson("male: ", vecTemp);

	vecTemp = pFemaleCriteria->doFilter(vecPersons);
	printPerson("female: ", vecTemp);

	vecTemp = pAgeCriteria->doFilter(vecPersons);
	printPerson("age>26: ", vecTemp);

	vecTemp = pEduCriteria->doFilter(vecPersons);
	printPerson("benke: ", vecTemp);

	vecTemp = pAndCriteria->doFilter(vecPersons);
	printPerson("benke and male: ", vecTemp);

	vecTemp = pOrCriteria->doFilter(vecPersons);
	printPerson("age>26 or female: ", vecTemp);

	vecTemp = pAndCriteriaEx->doFilter(vecPersons);
	printPerson("age>26 and benke and female: ", vecTemp);

	vecTemp = pOrCriteriaEx->doFilter(vecPersons);
	printPerson("age>26 or benke or male or female: ", vecTemp);

	for (auto& it : vecTemp) {
		delete it;
	}
	delete pMaleCriteria;
	delete pFemaleCriteria;
	delete pAgeCriteria;
	delete pEduCriteria;
	delete pAndCriteria;
	delete pOrCriteria;
	delete pAndCriteriaEx;
	delete pOrCriteriaEx;
}

输出:

male: 
[name:liu bin;sex:male;age:39;education:benke]
[name:he nan shan;sex:male;age:44;education:boshi]
[name:guo dong;sex:male;age:27;education:zhuanke]
[name:mei duo;sex:male;age:10;education:xiaoxue]

female: 
[name:li xiang;sex:female;age:25;education:zhuanke]
[name:san ling;sex:female;age:56;education:suoshi]
[name:jing gang shan;sex:female;age:32;education:suoshi]
[name:shan shan;sex:female;age:41;education:benke]

age>26: 
[name:liu bin;sex:male;age:39;education:benke]
[name:he nan shan;sex:male;age:44;education:boshi]
[name:san ling;sex:female;age:56;education:suoshi]
[name:guo dong;sex:male;age:27;education:zhuanke]
[name:jing gang shan;sex:female;age:32;education:suoshi]
[name:shan shan;sex:female;age:41;education:benke]

benke: 
[name:liu bin;sex:male;age:39;education:benke]
[name:shan shan;sex:female;age:41;education:benke]

benke and male: 
[name:liu bin;sex:male;age:39;education:benke]

age>26 or female: 
[name:li xiang;sex:female;age:25;education:zhuanke]
[name:san ling;sex:female;age:56;education:suoshi]
[name:jing gang shan;sex:female;age:32;education:suoshi]
[name:shan shan;sex:female;age:41;education:benke]
[name:liu bin;sex:male;age:39;education:benke]
[name:he nan shan;sex:male;age:44;education:boshi]
[name:guo dong;sex:male;age:27;education:zhuanke]

age>26 and benke and female: 
[name:shan shan;sex:female;age:41;education:benke]

age>26 or benke or male or female: 
[name:liu bin;sex:male;age:39;education:benke]
[name:he nan shan;sex:male;age:44;education:boshi]
[name:guo dong;sex:male;age:27;education:zhuanke]
[name:mei duo;sex:male;age:10;education:xiaoxue]
[name:li xiang;sex:female;age:25;education:zhuanke]
[name:san ling;sex:female;age:56;education:suoshi]
[name:jing gang shan;sex:female;age:32;education:suoshi]
[name:shan shan;sex:female;age:41;education:benke]

3.过滤器模式的优点

过滤器模式通过提供一种灵活的方式来处理和筛选对象集合,从而提高代码的灵活性和可维护性。

灵活性过滤器模式充许根据不同的过滤条件对请求进行筛选和传递,这意味看你可以轻松地添加、删除或修改过滤器,而无需修改客户端代码,这使得系统更加灵活,能够适应不同的需求和变化。

可扩展性由于过滤器模式是可扩展的,你可以在不影响现有代码的情况下添加新的过滤器,这有助于降低代码的耦合度,提高模块化程度,使代码更易于维护和扩展。

复用性每个过滤器都可以独立地实现其过滤逻辑,这意味着它们是可复用的,你可以在不同的场景下使用相同的过滤器或者将多个过滤器组合在一起以满足更复杂的过滤需求。

解耦通过将过滤逻辑封装在独立的过滤器中,过滤器模式降低了客户端代码与具体过滤逻辑之间的耦合度,这意味看你可以在不改变客户端代码的情况下更改或替换过滤器,提高了  代码的可维护性。

易于测试由于每个过滤器都是独立的,你可以单独测试每个过滤器,确保它们按照预期工作,这有助于提高代码的可测讨性和可维护性。

简化复杂逻辑通过将复杂的筛选逻辑分解为一系列简单的过滤步骤,过滤器模式可以使代码更易于理解和维护,每个过滤器只关注一个特定的筛选条件,从而使代码更加清晰和模块化。

4.过滤器模式的不足

性能问题当数据集合非常大时,大量的迭代运算,过滤器模式可能会降低程序性能。每次过滤都需要遍历整个数据集合,这可能会降低程序的运行效率。

配置复杂性当需要组合多个过滤器时,可能需要编写大量的配置代码,这可能会增加代码的复杂性。

5.适用的场景

1) 数据筛选

在数据处理中,经常需要对大量的数据进行筛选,以满足特定条件。过滤器设计模式可以将这种需求抽象化,通过定义一个过滤器接口,实现不同的筛选逻辑。这种设计模式可以方便地扩展和修改,满足不同的筛选需求。

2) 请求过滤

在Web应用程序中,通常需要对接收到的请求进行筛选和过滤,例如检查用户身份、过滤目的地址请求等。使用过滤器设计模式,可以将请求的筛选逻辑封装在过滤器中,对每个请求进行处理。这种设计模式可以提高代码的可维护性和可扩展性;在这点上由此可以派生出拦截过滤器模式,需要了解的可以点进去看看,在这里就不过多细说了。

3) 事件过滤

在事件驱动的系统中,经常需要对事件进行筛选和过滤。例如,在事件总线中,可能需要对事件进行分类和筛选,以便将事件分发给不同的消费者。过滤器设计模式可以将这种需求抽象化,通过定义一个一致的过滤器接口,实现不司的事件筛选逻辑。

4) 日志过滤

在日志记录中,通常需要对日志消息进行筛选和过滤,以满定不同的需求。例如,可能需要根据志级别、日志内容等信息进行筛选和过滤。过滤器设计模式可以将这种需求抽象化通过定义一个日志过滤器接口,实现不同的日志筛选逻辑。

5) 数据流过滤

在数据处理流中,经常需要对数据进行筛选和过滤。例如,在流处理中,可能需要对数据进行分类、去重、转换等操作。过滤器设计模式可以将这种需求抽象化,通过定义一个数据流过滤器接口,实现不同的数据筛选逻辑。这种设计模式可以提高数据处理流的灵活性和可抗展性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/304513.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

5.5 THREAD GRANULARITY

性能调优中一个重要的算法决定是线程的粒度。有时&#xff0c;在每个线程中投入更多工作并使用更少的线程是有利的。当线程之间存在一些冗余工作时&#xff0c;就会产生这种优势。在当前一代设备中&#xff0c;每个SM的指令处理带宽有限。每个指令都消耗指令处理带宽&#xff0…

迎接人工智能的下一个时代:ChatGPT的技术实现原理、行业实践以及商业变现途径

课程背景 2023年&#xff0c;以ChatGPT为代表的接近人类水平的对话机器人&#xff0c;AIGC不断刷爆网络&#xff0c;其强大的内容生成能力给人们带来了巨大的震撼。学术界和产业界也都形成共识&#xff1a;AIGC绝非昙花一现&#xff0c;其底层技术和产业生态已经形成了新的格局…

【数据结构 | 二叉树入门】

数据结构 | 二叉树入门 二叉树概念&#xff1a;二叉树特点&#xff1a;二叉树的基本形态特殊二叉树满二叉树完全二叉树 二叉树的存储结构二叉树的遍历先序遍历中序遍历后序遍历 计算二叉树的节点个数计算叶子节点的个数树的高度求第k层节点个数 二叉树概念&#xff1a; 如下图…

【51单片机】延时函数delay的坑——关于无符号整型数据for语句“x >= 0“变成死循环

请认真看看以下延时函数是否正确&#xff0c;并且指出错误&#xff1a;&#xff08;考考C语言功底&#xff09; void delay_ms(unsigned int xms) //delay x ms {unsigned int x,y;for(xxms;x>0;x--)for(y124;y>0;y--); }废话少说&#xff0c;上正确代码&#xff1a; v…

python进阶 -- 日志装饰器详解

日志 日志&#xff1a;记录程序运行的时候&#xff0c;出现的问题&#xff0c;或者说验证流程是否正常 在实际工作中&#xff0c;python的脚本命令一般是放在服务器执行的linux系统 日志其实就是记录程序运行时出现的问题、或者正常的打印&#xff0c;协助出现问题的时解决排查…

以太网交换机——稳定安全,构筑数据之桥

交换机&#xff0c;起源于集线器和网桥等网络通信设备&#xff0c;它在性能和功能上有了很大的发展&#xff0c;因此逐渐成为搭建网络环境的常用的设备。 随着ChatGPT爆发&#xff0c;因为用户量激增而宕机事件频频发生&#xff0c;云计算应用催生超大规模算力需求&#xff0c;…

kubernetes Namespace Labels 详解

写在前面&#xff1a;如有问题&#xff0c;以你为准&#xff0c; 目前24年应届生&#xff0c;各位大佬轻喷&#xff0c;部分资料与图片来自网络 内容较长&#xff0c;页面右上角目录方便跳转 namespace 实现资源分组&#xff0c;label实现业务分组 Namespace 基础理论 最重…

Spring AOP(详解)

目录 1.AOP概述 2.AOP相关术语 3.Spring AOP的原理机制 3.1JDK动态代理 3.2 CGLIB动态代理 3.3简单代码展示 3.3.1JDK动态代理 3.3.2CGLIB动态代理 4.Spring的AOP配置 4.1pom.xml 4.2增强方法 4.3切点 4.4切面 5.基于注解的AOP配置 5.1.创建工程 5.2.增强 5.3AOP…

使用flet创建todo应用

使用 Flet 在 Python 中创建待办事项应用 Create To-Do app in Python with Flet 翻译官网教程https://flet.dev/docs/tutorials/python-todo&#xff0c;对一些地方进行了注释和修改。 安装flet Python版本需要3.8及以上&#xff0c;使用pip安装&#xff1a; pip install…

YY9706.102-2021 医疗设备EMC检测知识-RE

一&#xff1a;RE&#xff08;辐射发射试验&#xff09; 按照GB 4824 6.2.2电磁辐射骚扰限值描述&#xff0c;在相对应的实验室和距离测量时&#xff0c;选择不同的限值进行测量。 以上只列出了1组的A、B类限值&#xff0c;2组设备的限值在6.3章节有介绍&#xff0c;对于我们的…

Backtrader 文档学习-Strategy(下)

Backtrader 文档学习-Strategy&#xff08;下&#xff09; 1. notify_cashvalue # 测试 #notify_cashvalue 方法特点 class Test_Strategy(bt.Strategy): # 策略通用初始参数params ((maperiod1, 5),(maperiod2, 20),(printlog, True), # 写入日志标志(logfilename, Test_…

Vue-8、Vue事件处理

1、点击事件 <!DOCTYPE html> <html lang"en" xmlns:v-model"http://www.w3.org/1999/xhtml" xmlns:v-bind"http://www.w3.org/1999/xhtml"xmlns:v-on"http://www.w3.org/1999/xhtml"> <head><meta charset&quo…

计算机网络—— 概述

概述 1.1 因特网概述 网络、互联网和因特网 网络由若干结点和连接这些结点的链路组成多个网络还可以通过路由器互联起来&#xff0c;这样就构成了一个覆盖范围更大的网络&#xff0c;即互联网&#xff08;或互连网&#xff09;。因特网&#xff08;Internet&#xff09;是世…

react输入框检索树形(tree)结构

input搜索框搜索树形子级内容1. input框输入搜索内容2. 获取tree结构数据3. 与tree匹配输入的内容&#xff0c;tree是多维数组&#xff0c;一级一级的对比输入的内容是否匹配&#xff0c;用forEach循环遍历数据&#xff0c;匹配不到在往下找&#xff0c;直到找到为null &#x…

求求你,别再乱用@Transactional了

求求你&#xff0c;别再乱用Transactional了 文章目录 &#x1f50a;先看个问题&#x1f4d5;情况1情况1结果 &#x1f5a5;️情况2情况2结果 &#x1f4dc; 情况三情况3结果 &#x1f4d8;情况4情况4结果 &#x1f516;先说结论情况1结果情况2结果情况3结果情况4结果&#x1f…

oracle 12c pdb expdp/impdp 数据导入导出

环境 (源)rac 环境 byoradbrac 系统版本&#xff1a;Red Hat Enterprise Linux Server release 6.5 软件版本&#xff1a;Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit byoradb1&#xff1a;172.17.38.44 byoradb2&#xff1a;172.17.38.45 (目的&am…

2024年中职网络安全——Windows操作系统渗透测试(Server2105)

Windows操作系统渗透测试 任务环境说明&#xff1a; 服务器场景&#xff1a;Server2105服务器场景操作系统&#xff1a;Windows&#xff08;版本不详&#xff09;&#xff08;封闭靶机&#xff09;需要环境加Q 目录 1.通过本地PC中渗透测试平台Kali对服务器场景进行系统服务…

区块链金融科技:技术融合与挑战应对【文末送书-16】

文章目录 前言一.区块链与金融科技的融合&#xff1a;革新金融格局的技术之光1.1区块链技术简介1.2 区块链在金融科技中的应用 二.智能合约2.1 去中心化金融&#xff08;DeFi&#xff09;2.2区块链对金融科技的影响2.3数据安全性 三.区块链与金融科技【文末送书-16】3.1 粉丝福…

spring Security源码讲解-Sevlet过滤器调用springSecurty过滤器的流程

承接上文 上一节 http://t.csdnimg.cn/ueSAl 最后讲到了过滤器收集完成注入容器&#xff0c;这节我们来讲Security的Filter是怎么被Spring调用的。 我们先看webSecurity的performBuild方法(), ![在这里插入图片描述](https://img-b 也就是说&#xff0c;最终返回的过滤器对象…

如何利用大语言模型(LLM)打造定制化的Embedding模型

一、前言 在探索大语言模型&#xff08;LLM&#xff09;应用的新架构时&#xff0c;知名投资公司 Andreessen Horowitz 提出了一个观点&#xff1a;向量数据库是预处理流程中系统层面上最关键的部分。它能够高效地存储、比较和检索高达数十亿个嵌入&#xff08;也就是向量&…