JaveWeb使用的设计模型曹明

(给ImportNew加星标,提高Java技能)

作者:crazyant

www.crazyant.net/2022.html

虽然我们都知道有26个设计模式,但是大多停留在概念层面,真实开发中很少遇到,Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解设计模式。

Mybatis至少遇到了以下的设计模式的使用:

接下来挨个模式进行解读,先介绍模式自身的知识,然后解读在Mybatis中怎样应用了该模式。

1、Builder模式

Builder模式的定义是“将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。”,它属于创建类模式,一般来说,如果一个对象的构建比较复杂,超出了构造函数所能包含的范围,就可以使用工厂模式和Builder模式,相对于工厂模式会产出一个完整的产品,Builder应用于更加复杂的对象的构建,甚至只会构建产品的一个部分。

在Mybatis环境的初始化过程中,SqlSessionFactoryBuilder会调用XMLConfigBuilder读取所有的MybatisMapConfig.xml和所有的*Mapper.xml文件,构建Mybatis运行的核心对象Configuration对象,然后将该Configuration对象作为参数构建一个SqlSessionFactory对象。

其中XMLConfigBuilder在构建Configuration对象时,也会调用XMLMapperBuilder用于读取*Mapper文件,而XMLMapperBuilder会使用XMLStatementBuilder来读取和build所有的SQL语句。

在这个过程中,有一个相似的特点,就是这些Builder会读取文件或者配置,然后做大量的XpathParser解析、配置或语法的解析、反射生成对象、存入结果缓存等步骤,这么多的工作都不是一个构造函数所能包括的,因此大量采用了Builder模式来解决。

对于builder的具体类,方法都大都用build*开头,比如SqlSessionFactoryBuilder为例,它包含以下方法:

即根据不同的输入参数来构建SqlSessionFactory这个工厂对象。

2、工厂模式

在Mybatis中比如SqlSessionFactory使用的是工厂模式,该工厂没有那么复杂的逻辑,是一个简单工厂模式。

简单工厂模式(SimpleFactoryPattern):又称为静态工厂方法(StaticFactoryMethod)模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

SqlSession可以认为是一个Mybatis工作的核心的接口,通过这个接口可以执行执行SQL语句、获取Mappers、管理事务。类似于连接MySQL的Connection对象。

可以看到,该Factory的openSession方法重载了很多个,分别支持autoCommit、Executor、Transaction等参数的输入,来构建核心的SqlSession对象。

在DefaultSqlSessionFactory的默认工厂实现里,有一个方法可以看出工厂怎么产出一个产品:

privateSqlSessionopenSessionFromDataSource(ExecutorTypeexecType,TransactionIsolationLevellevel,booleanautoCommit){Transactiontx=null;try{finalEnvironmentenvironment=configuration.getEnvironment();finalTransactionFactorytransactionFactory=getTransactionFactoryFromEnvironment(environment);tx=transactionFactory.newTransaction(environment.getDataSource(),level,autoCommit);finalExecutorexecutor=configuration.newExecutor(tx,execType);returnnewDefaultSqlSession(configuration,executor,autoCommit);}catch(Exceptione){closeTransaction(tx);//mayhavefetchedaconnectionsoletscall//close()throwExceptionFactory.wrapException("Erroropeningsession.Cause:"+e,e);}finally{ErrorContext.instance().reset();}}

这是一个openSession调用的底层方法,该方法先从configuration读取对应的环境配置,然后初始化TransactionFactory获得一个Transaction对象,然后通过Transaction获取一个Executor对象,最后通过configuration、Executor、是否autoCommit三个参数构建了SqlSession。

在这里其实也可以看到端倪,SqlSession的执行,其实是委托给对应的Executor来进行的。

而对于LogFactory,它的实现代码:

publicfinalclassLogFactory{privatestaticConstructorlogConstructor;privateLogFactory(){//disableconstruction}publicstaticLoggetLog(Class<>aClass){returngetLog(aClass.getName());}

这里有个特别的地方,是Log变量的的类型是Constructor,也就是说该工厂生产的不只是一个产品,而是具有Log公共接口的一系列产品,比如Log4jImpl、Slf4jImpl等很多具体的Log。

3、单例模式

单例模式(SingletonPattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。

单例模式的要点有三个:一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。单例模式是一种对象创建型模式。单例模式又名单件模式或单态模式。

在Mybatis中有两个地方用到单例模式,ErrorContext和LogFactory,其中ErrorContext是用在每个线程范围内的单例,用于记录该线程的执行环境错误信息,而LogFactory则是提供给整个Mybatis使用的日志工厂,用于获得针对项目配置好的日志对象。

ErrorContext的单例实现代码:

publicclassErrorContext{privatestaticfinalThreadLocalLOCAL=newThreadLocal();privateErrorContext(){}publicstaticErrorContextinstance(){ErrorContextcontext=LOCAL.get();if(context==null){context=newErrorContext();LOCAL.set(context);}returncontext;}

构造函数是private修饰,具有一个static的局部instance变量和一个获取instance变量的方法,在获取实例的方法中,先判断是否为空如果是的话就先创建,然后返回构造好的对象。

只是这里有个有趣的地方是,LOCAL的静态实例变量使用了ThreadLocal修饰,也就是说它属于每个线程各自的数据,而在instance()方法中,先获取本线程的该实例,如果没有就创建该线程独有的ErrorContext。

4、代理模式

代理模式可以认为是Mybatis的核心使用的模式,正是由于这个模式,我们只需要编写Mapper.java接口,不需要实现,由Mybatis后台帮我们完成具体SQL的执行。

代理模式(ProxyPattern):给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式的英文叫做Proxy或Surrogate,它是一种对象结构型模式。

代理模式包含如下角色:

这里有两个步骤,第一个是提前创建一个Proxy,第二个是使用的时候会自动请求Proxy,然后由Proxy来执行具体事务;

当我们使用Configuration的getMapper方法时,会调用mapperRegistry.getMapper方法,而该方法又会调用mapperProxyFactory.newInstance(sqlSession)来生成一个具体的代理:

/***@authorLasseVoss*/publicclassMapperProxyFactory{privatefinalClassmapperInterface;privatefinalMapmethodCache=newConcurrentHashMap();publicMapperProxyFactory(ClassmapperInterface){this.mapperInterface=mapperInterface;}publicClassgetMapperInterface(){returnmapperInterface;}publicMapgetMethodCache(){returnmethodCache;}@SuppressWarnings("unchecked")protectedTnewInstance(MapperProxymapperProxy){return(T)Proxy.newProxyInstance(mapperInterface.getClassLoader(),newClass[]{mapperInterface},mapperProxy);}publicTnewInstance(SqlSessionsqlSession){finalMapperProxymapperProxy=newMapperProxy(sqlSession,mapperInterface,methodCache);returnnewInstance(mapperProxy);}}

在这里,先通过TnewInstance(SqlSessionsqlSession)方法会得到一个MapperProxy对象,然后调用TnewInstance(MapperProxymapperProxy)生成代理对象然后返回。

而查看MapperProxy的代码,可以看到如下内容:

publicclassMapperProxyimplementsInvocationHandler,Serializable{@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{try{if(Object.class.equals(method.getDeclaringClass())){returnmethod.invoke(this,args);}elseif(isDefaultMethod(method)){returninvokeDefaultMethod(proxy,method,args);}}catch(Throwablet){throwExceptionUtil.unwrapThrowable(t);}finalMapperMethodmapperMethod=cachedMapperMethod(method);returnmapperMethod.execute(sqlSession,args);}

非常典型的,该MapperProxy类实现了InvocationHandler接口,并且实现了该接口的invoke方法。

通过这种方式,我们只需要编写Mapper.java接口类,当真正执行一个Mapper接口的时候,就会转发给MapperProxy.invoke方法,而该方法则会调用后续的sqlSession.cud>executor.execute>prepareStatement等一系列方法,完成SQL的执行和返回。

5、组合模式

组合模式组合多个对象形成树形结构以表示“整体-部分”的结构层次。

组合模式对单个对象(叶子对象)和组合对象(组合对象)具有一致性,它将对象组织到树结构中,可以用来描述整体与部分的关系。同时它也模糊了简单元素(叶子对象)和复杂元素(容器对象)的概念,使得客户能够像处理简单元素一样来处理复杂元素,从而使客户程序能够与复杂元素的内部结构解耦。

在使用组合模式中需要注意一点也是组合模式最关键的地方:叶子对象和组合对象实现相同的接口。这就是组合模式能够将叶子节点和对象节点进行一致处理的原因。

Mybatis支持动态SQL的强大功能,比如下面的这个SQL:

UPDATEusersname=#{name},age=#{age},birthday=#{birthday}whereid=${id}

在这里面使用到了trim、if等动态元素,可以根据条件来生成不同情况下的SQL;

在DynamicSqlSource.getBoundSql方法里,调用了rootSqlNode.apply(context)方法,apply方法是所有的动态节点都实现的接口:

publicinterfaceSqlNode{booleanapply(DynamicContextcontext);}

对于实现该SqlSource接口的所有节点,就是整个组合模式树的各个节点:

组合模式的简单之处在于,所有的子节点都是同一类节点,可以递归的向下执行,比如对于TextSqlNode,因为它是最底层的叶子节点,所以直接将对应的内容append到SQL语句中:

@Overridepublicbooleanapply(DynamicContextcontext){GenericTokenParserparser=createParser(newBindingTokenParser(context,injectionFilter));context.appendSql(parser.parse(text));returntrue;}

但是对于IfSqlNode,就需要先做判断,如果判断通过,仍然会调用子元素的SqlNode,即contents.apply方法,实现递归的解析。

@Overridepublicbooleanapply(DynamicContextcontext){if(evaluator.evaluateBoolean(test,context.getBindings())){contents.apply(context);returntrue;}returnfalse;}

6、模板方法模式

模板方法模式是所有模式中最为常见的几个模式之一,是基于继承的代码复用的基本技术。

模板方法模式需要开发抽象类和具体子类的设计师之间的协作。一个设计师负责给出一个算法的轮廓和骨架,另一些设计师则负责给出这个算法的各个逻辑步骤。代表这些具体逻辑步骤的方法称做基本方法(primitivemethod);而将这些基本方法汇总起来的方法叫做模板方法(templatemethod),这个设计模式的名字就是从此而来。

模板类定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

在Mybatis中,sqlSession的SQL执行,都是委托给Executor实现的,Executor包含以下结构:

其中的BaseExecutor就采用了模板方法模式,它实现了大部分的SQL执行逻辑,然后把以下几个方法交给子类定制化完成:

protectedabstractintdoUpdate(MappedStatementms,Objectparameter)throwsSQLException;protectedabstractListdoFlushStatements(booleanisRollback)throwsSQLException;protectedabstractListdoQuery(MappedStatementms,Objectparameter,RowBoundsrowBounds,ResultHandlerresultHandler,BoundSqlboundSql)throwsSQLException;

该模板方法类有几个子类的具体实现,使用了不同的策略:

比如在SimpleExecutor中这样实现update方法:

@OverridepublicintdoUpdate(MappedStatementms,Objectparameter)throwsSQLException{Statementstmt=null;try{Configurationconfiguration=ms.getConfiguration();StatementHandlerhandler=configuration.newStatementHandler(this,ms,parameter,RowBounds.DEFAULT,null,null);stmt=prepareStatement(handler,ms.getStatementLog());returnhandler.update(stmt);}finally{closeStatement(stmt);}}

7、适配器模式

适配器模式(AdapterPattern):将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。

在Mybatsi的logging包中,有一个Log接口:

/***@authorClintonBegin*/publicinterfaceLog{booleanisDebugEnabled();booleanisTraceEnabled();voiderror(Strings,Throwablee);voiderror(Strings);voiddebug(Strings);voidtrace(Strings);voidwarn(Strings);}

该接口定义了Mybatis直接使用的日志方法,而Log接口具体由谁来实现呢?Mybatis提供了多种日志框架的实现,这些实现都匹配这个Log接口所定义的接口方法,最终实现了所有外部日志框架到Mybatis日志包的适配:

比如对于Log4jImpl的实现来说,该实现持有了org.apache.log4j.Logger的实例,然后所有的日志方法,均委托该实例来实现。

publicclassLog4jImplimplementsLog{privatestaticfinalStringFQCN=Log4jImpl.class.getName();privateLoggerlog;publicLog4jImpl(Stringclazz){log=Logger.getLogger(clazz);}@OverridepublicbooleanisDebugEnabled(){returnlog.isDebugEnabled();}@OverridepublicbooleanisTraceEnabled(){returnlog.isTraceEnabled();}@Overridepublicvoiderror(Strings,Throwablee){log.log(FQCN,Level.ERROR,s,e);}@Overridepublicvoiderror(Strings){log.log(FQCN,Level.ERROR,s,null);}@Overridepublicvoiddebug(Strings){log.log(FQCN,Level.DEBUG,s,null);}@Overridepublicvoidtrace(Strings){log.log(FQCN,Level.TRACE,s,null);}@Overridepublicvoidwarn(Strings){log.log(FQCN,Level.WARN,s,null);}}

8、装饰者模式

装饰模式(DecoratorPattern):动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。其别名也可以称为包装器(Wrapper),与适配器模式的别名相同,但它们适用于不同的场合。根据翻译的不同,装饰模式也有人称之为“油漆工模式”,它是一种对象结构型模式。

在mybatis中,缓存的功能由根接口Cache(org.apache.ibatis.cache.Cache)定义。整个体系采用装饰器设计模式,数据存储和缓存的基本功能由PerpetualCache(org.apache.ibatis.cache.impl.PerpetualCache)永久缓存实现,然后通过一系列的装饰器来对PerpetualCache永久缓存进行缓存策略等方便的控制。如下图:

用于装饰PerpetualCache的标准装饰器共有8个(全部在org.apache.ibatis.cache.decorators包中):

另外,还有一个特殊的装饰器TransactionalCache:事务性的缓存

正如大多数持久层框架一样,mybatis缓存同样分为一级缓存和二级缓存

二级缓存对象的默认类型为PerpetualCache,如果配置的缓存是默认类型,则mybatis会根据配置自动追加一系列装饰器。

Cache对象之间的引用顺序为:

SynchronizedCache–>LoggingCache–>SerializedCache–>ScheduledCache–>LruCache–>PerpetualCache

9、迭代器模式

迭代器(Iterator)模式,又叫做游标(Cursor)模式。GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。

Java的Iterator就是迭代器模式的接口,只要实现了该接口,就相当于应用了迭代器模式:

比如Mybatis的PropertyTokenizer是property包中的重量级类,该类会被reflection包中其他的类频繁的引用到。这个类实现了Iterator接口,在使用时经常被用到的是Iterator接口中的hasNext这个函数。

publicclassPropertyTokenizerimplementsIterator{privateStringname;privateStringindexedName;privateStringindex;privateStringchildren;publicPropertyTokenizer(Stringfullname){intdelim=fullname.indexOf('.');if(delim>-1){name=fullname.substring(0,delim);children=fullname.substring(delim+1);}else{name=fullname;children=null;}indexedName=name;delim=name.indexOf('[');if(delim>-1){index=name.substring(delim+1,name.length()-1);name=name.substring(0,delim);}}publicStringgetName(){returnname;}publicStringgetIndex(){returnindex;}publicStringgetIndexedName(){returnindexedName;}publicStringgetChildren(){returnchildren;}@OverridepublicbooleanhasNext(){returnchildren!=null;}@OverridepublicPropertyTokenizernext(){returnnewPropertyTokenizer(children);}@Overridepublicvoidremove(){thrownewUnsupportedOperationException("Removeisnotsupported,asithasnomeaninginthecontextofproperties.");}}

可以看到,这个类传入一个字符串到构造函数,然后提供了iterator方法对解析后的子串进行遍历,是一个很常用的方法类。

参考资料:

首先spring,相信大家都很熟悉了。

1、轻量级零配置,API使用简单

2、面向Bean只需要编写普通的Bean(一个Bean代表一个对象)

3、松耦合充分利用AOP思想)(各自可以独立开发,然后整合起来运行)

4、万能胶与主流框架无缝集成(Mybatisdubbo等等)

5、设计模式将Java中经典的设计模式运用的淋漓尽致

Spring解决企业级应用开发的负责设计,简化开发。

1,基于POJO的清理爱你国际和最小侵入性(代码的嵌套,独自开发合起来运行)

2,通过依赖注入和面向接口松耦合

4、通过切面和模板减少版式代码

主要通过,面向Bean、依赖注入以及面向切面三种方式达成

Spring提供了IOC容器,通过配置文件或者注解的方式来管理对象之间的依赖关系

Aa=newA()//实例化后用一个变量保存下来(匿名对象)------------------》Spring用IOC容器存储起来~

a.c()//必须初始化才运行----------------------->Spring帮忙初始化,实例化(控制器给了spring)

最终实现了依赖注入:

@autowriteInterfaAa//自动吧他的实现类注入进来

@Resource(“aa”)//IOC容器种类的id为“aa”的对象自动注入到这里

@autowriteAa//根据类型自动注入

Spring的注入方式

1、setter

2、构造方法

3、强制赋值

面向切面,AOP核心思想--解耦!把一个整体拆开,分别开发,发布时候,再组装到一起运行,切面就是规则!

比如事务;

开启事务执行事务事务回滚关闭事务这就是规则!!!!!!

这种有规律的,就可以认为他是固定的,可以单独拿出来开发设计,作为一个模块(比如日志啊)。

AOP就是个编程思想而已

关于Spring的使用,特点,网上资料很多,大家可以自己找找学习下。本博客主要对于源码进行解读。

AOP的功能完全集成到了Spring事务管理、日志和其他各种特性的上下文中

authentication权限认证

Logging日志

TransctionsManager事务

LazyLoading懒加载

ContexProcess上下文处理

ErrorHandler错误跟踪(异常捕获机制)

Cache缓存

1、除了AOP以外的设计模式

a、代理模式

b、工厂模式

c、单例模式

d、委派模式

e、策略模式

f、策略模式

g、原型模式

代理模式原理:

1、拿到被代理对象的引用,然后获取它的接口

2、JDK代理重新生成一个类,同时实现我们给的代理对象所实现的接口

3、把代理对象的引用拿到

4、重新动态生成一个class字节码

5、编译

动态代理调用哪个方法就代理哪个方法

整个类生成一个新的类

大家认真仔细研究好代理模式,代理模式在Spring中应用非常广泛!!!

JDK代理模式实现:

1、定义接口

2、定义实现接口的类

3、代理类,代理类需要实现InvocationHandler接口,然后实现invoke方法

实现这个接口

不用jdk的任何东西!

首先规定有个InvocationHandler有个invoke方法

importjava.lang.reflect.Method;publicinterfaceGPInvocationHandler{publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable;}实现个Proxy里面有InvocationHandler引用有newInstance的方法classloader方法

JDK必须实现接口!!!!

满足代理模式应用场景的三个必要条件,

1、需要有两个角色执行者和被代理对象

2、注重过程,必须要做,被代理对象不做

3、执行者必须拿到被代理对象的资料(执行者持有被代理对象的引用)

代理模式总结到底层就是:字节码重组!(字节码重组时候对象要强制转换,必须要实现一个接口)

Java源代码--->编译---->字节码(在原始的加了东西)-->加载到jvm中

然后cglib不需要,Spring主要用的cglib做动态代理定义一个类自动生成一个类自动继承这个类子类引用指向父类看下面:

(同样做了字节码重组事情)

是继承关系

代理可以实现在每一个方法调用之前加一些代码,方法嗲用之后加一些代码

AOP:事务代理、日志监听

Service方法开启一个事务事务的执行是由我们自己的代码完成的

1、监听到是否有异常,可能需要根据异常的类型来决定这个事务是否好回滚or继续提交?(commitorrollback?)

2、事务要关闭掉

通过动态代理给加了代码

-------------------------------------工厂模式

首先要区分生产者消费者消费者不关心工厂、过程只关心结果从工厂取东西哈哈

简单工厂:

定义接口:

定义工厂接口

实现不同工厂

消费者使用

1、定义工厂接口

这个不再是接口了而是抽象类

抽象类可以引用自己的方法!

默认的方法

单例模式:

整个系统从启动到终止,自会有一个实例

在应用中遇到功能性冲突的时候,需要用到单例模式

单例模式有7种写法!!!

1.

3、

委派模式:

1类似中介的功能(委托机制)

2只有被委托人的引用

两个角色受托人委托人

定义一个接口

关于策略模式,参考系Comparator方法就可以啦返回-101这种的

a、比较器接口

b、调用时候有自己的实现

首先要设计个原型

实现Cloneable接口

模板(固定的执行流程)

定义冲饮料的机器:

是Java的规范各个数据库厂商去实现

1、加载驱动类DriverManager

2、建立连接

3、创建语句集(标准语句集、预处理语句集)(语句集合?Mysqloraclesqlserveraccess语句不太一样哦)

4、执行语句集

5、结果集ResultSet游标

ORM(连接的是哪个对象映射哪个结果Listor自定义的类还是??运行时候才知道)

THE END
1.快准狠了解相亲对象,就聊这9方面恋爱学堂360期必须提交真实有效的信息且怀有真诚找对象的心,一旦发现伪单身或信息虚假,立即拉黑注销。 资料准备: 请将个人姓名、年龄、身高、职业、择偶要求、联系方式及自我介绍,发给龚州爱相亲平台红娘老师。至少附2张个人照片(生活照、写真照均可) 如何脱单: https://mp.weixin.qq.com/s?__biz=MzA3ODQ1NDA5Mw==&mid=2468306665&idx=2&sn=cab0b087ee9b52e57ee1ca8e37b749b0&chksm=883de25164a6c08f85e1f0f9195ae51fa00eb2677f92fd183fcc5df521dd50468c64c6eb6a14&scene=27
2.两名女子花钱找对象不料“婚介公司”关门了(图)同样在怦然网公司购买了相亲服务的韦女士表示,她花了2999元购买了其中一个套餐。按照该套餐内容显示,公司得提供至少20名相亲男士的联系方式给韦女士,但她也只拿到了3名男士的联系方式,而且都还没见过面。 记者走访 “婚介公司”人去楼空,客户资料散落现场 https://www.gxnews.com.cn/staticpages/20180921/newgx5ba49694-17665993.shtml
3.相亲对象不主动联系我怎么办接亲网如果你相亲的对象是女孩,人家多半是不可能会主动的,除非是她非常心动。一般来说,一次见面后就主动是一件非常伤及面子的事情,如果你喜欢女孩子,不妨自己先开口。她对你有感觉,你们自然会有发展空间! 二、相亲对象不主动联系我怎么办 1、拿到他的全部资料 https://www.jieqinwang.com/baike/8294
4.七夕活动创意方案(精选14篇)活动形式:相亲会、游园、嘉年华 活动对象:高端优质单身男女青年 活动人数:300-500人 报名方式:微信公众号平台招募 二、活动亮点 一、现场穿越回古代 现场工作人员及互动游戏工作人员,分别cos成仙女和仙童,还有姻缘台月老,以及各个互动游戏区域工作人员等穿着古装,让现场嘉宾集体穿越到古代,寻找有缘人 https://www.360wenmi.com/f/fileb1tus2s3.html
5.“会费”交了,相亲对象找不到了……有约频道经询问得知,2021年8月,邓某看到一则电视征婚广告,单身的邓某按照留下的联系方式拨打过去,对方自称是重庆江北“君相媛婚姻介绍服务部”的公司“红娘”,在简要问询邓某的择偶要求后,“红娘”当即承诺只要缴纳5800元会费,就可以安排优质对象相亲,不满意包换。http://youyue.youth.cn/yw/202207/t20220704_13819863.htm
6.《闪婚豪门:相亲对象是大佬全本小说推荐》小说最新章节免费阅读闪婚豪门:相亲对象是大佬全本小说推荐绯酒 著 现代都市连载现代言情《闪婚豪门:相亲对象是大佬》,现已完结,主要人物是许南音陆南骁,文章的原创作者叫做“绯酒”,非常的有看点,小说精彩剧情讲述的是:于阔点点头,“的确有一个。”“那你打算让谁去上这个节目?”东盛除了于阔,就是何雅名望最高,于阔并不喜欢抛头http://www.bynrtzb.org.cn/byxs/622517/
7.陕西单身被逼婚比率最高父母“摆摊”为儿女相亲婚恋市场父母“摆摊”为儿女相亲 一位女士要给记者找对象 年轻人工作生活节奏快时间少、生活压力大,西安有的家长在公园“摆摊”为儿女相亲。华商报记者日前来到西安市革命公园,看到广场一侧树上挂着许多传单,传单上张贴着单身男女的信息,有的手写有的打印,还有的直接附着照片,有许多人在查看资料。 https://news.hsw.cn/system/2017/0228/673783.shtml
8.《公户女Alpha[ABO]》刀尔^第1章^最新更新:202109都知道,几个月前,段廷议家里给他安排相亲。相亲对象还是个公户在职alpha。以为见一面就能应付过去的事。都没想到,喜欢呼朋唤友,四处找乐子的段廷议,能和对方保持联系这么久。 一开始朋友们都不怎么上心,时间久了,多少生出点好奇心来。 光屏里,穿着一身蓝白防护服的周言昭,正站在商场一楼,正在指挥现场防控https://www.jjwxc.net/onebook.php?novelid=5619031&chapterid=1
9.10年撮合3000对新人结婚,宋大姐的“牵手热线”太牛了!相亲对象不妨去见三次 “有些女孩子很挑剔,说为她们介绍对象,可刚拿到男方登记的一张纸就开始挑了。”身高没到175厘米,学历不是本科,头发好像有点不茂盛,工作不是体制内……宋大姐说,有时真怀疑她们是不是特别爱吃鱼,那么会挑刺。 对这样的挑刺型女生,大姐一般会主动“启发”对方:每个人心目中都有一个理想型https://www.nbwbw.com/article.php?id=119522
10.校园活动策划方案(15篇)(二)明白中学生交往的主要对象是老师、同学和家长。 (三掌握正确处理好与同学、老师和家长之间关系的技巧,注意提高自己的交往能力。 二、活动重点: 着重启发学生注意提高交往的技巧,包括在家如何与父母相处,在校如何与老师、同学相处,在校外如何与他人交往。 https://www.unjs.com/huodongfangan/202211/5949204.html
11.广州地铁21号线天河公园站竟藏着中国有名的“相亲公园”!热闹堪比90后设计师冰冰(化名)表示,她的妈妈觉得长相不重要,给她介绍的对象经济实力强,而她见到相亲对象后“两眼一黑”。她说:“我爸爸长的很帅,妈妈怎么忍心给女儿介绍这样的对象?”在天河公园,她曾花100多元请人在双休日帮忙挂资料,可能因为自己老家在外省,所以只有三四个还不错的男生主动联系她。 http://www.360doc.com/content/24/0302/10/7108612_1115748667.shtml
12.和联姻对象还是不熟知道今年的2.13号我对象跟我说,明天要去客户家吃饭,所以明天情人节就不能陪我过了,我虽然有一点不开心但也觉得这是没办法的事所以就同意了,然后我们就13号的 8128164 三国全面战争吧 love大中志正 招不到女武将,没有合适联姻对象,有没有其他办法结婚 分享164 婚姻吧 风月无情 相亲对象有个弟弟不务正业,还要https://tieba.baidu.com/mo/q/hybrid/search?keyword=%E5%92%8C%E8%81%94%E5%A7%BB%E5%AF%B9%E8%B1%A1%E8%BF%98%E6%98%AF%E4%B8%8D%E7%86%9F