我记得以前有人跟我说,“面试的时候要看spring的源码,要看ioc、aop的源码"那为什么要看这些开源框架的源码呢,其实很多人都是"应急式"的去读,就像读一篇文章一下,用最快的速度把文章从头到尾读一遍,那结果就是当你读完它,你也不清楚它讲了一个什么故事,想表达什么。
一个优秀的架构的源码我认为就好像一本名著一样,你的“文学”水平越高,你就越能读出作者设计的精妙之处。一篇源码在你不同水平的时候,能读出不同的东西,因此,我觉得优秀的框架的源码是经久不衰的,反复读多少次都不嫌多,直到你能设计出预期并驾齐驱甚至超越它的优美的架构。
读源码起初是一件很痛苦的事儿,想赶紧把它像流水账一样的读完;慢慢实力增强后,会感觉到读源码能够不费力气的读通;再假以时日,就能看出这些精妙的设计模式的组合。我有一个朋友,典型的源码痴狂症,他跟我说他第一次看见spring的源码,感觉特别兴奋,读了一宿没睡觉.......好吧,我还有很长的路需要走~
话说多了,我们赶紧入正题:
JFinal的框架我24号的一篇博文写到过,它优秀的地方在精简代码上,那么有两处源码是我觉得是值得我们要好好解析一下,一处是初始化加载—servlet跳转,另一处是DB+ActiveRecord的映射。
那么DB映射相对比较简单,我们这次就先来看看。
首先我们看看代码,还是之前我写过的 dog与cat的故事。
// 采用DB+ActiveRecord模式
ActiveRecordPlugin arp = new ActiveRecordPlugin(c3p0Plugin);
me.add(arp);
// 进行DB映射
arp.addMapping(" animal " , AnimalModel.class );
第一步:为ActiveRecordPlugin的 private IDataSourceProvider dataSourceProvider 赋值。 这三行代码就是加载DB映射的关键,那么我们复习一下,JFinal的DB映射无需配置文件,无需与DB对应的POJO,只需要写一个类,继承Model即可。
那么我们先来看看ActiveRecordPlugin的构造器。
public ActiveRecordPlugin(IDataSourceProvider dataSourceProvider) {
this (DbKit.MAIN_CONFIG_NAME, dataSourceProvider);
}
这里重要的是dataSourceProvider,IDataSourceProvider是一个接口,它的运行时类型是
JFinal 源码分析 [DB+ActiveRecord]
那么,可以看到
this (DbKit.MAIN_CONFIG_NAME, dataSourceProvider);
这段代码又继续读取另一个重载的构造器,然后调用了
public ActiveRecordPlugin(String configName, IDataSourceProvider dataSourceProvider, int transactionLevel) {
if (StrKit.isBlank(configName))
throw new IllegalArgumentException(" configName can not be blank " );
if (dataSourceProvider == null )
throw new IllegalArgumentException(" dataSourceProvider can not be null " );
this .configName = configName.trim();
this .dataSourceProvider = dataSourceProvider;
this .setTransactionLevel(transactionLevel);
}
最重要的就是这行代码: this.dataSourceProvider = dataSourceProvider;
这时,ActiveRecordPlugin的static变量的dataSourceProvider就已经被赋为C3p0Plugin的实例了。
第二步:定义映射用POJO
public class AnimalModel extends Model {...}
这里Model的源码我们一会再看,现在不着急。
然后进行映射
// 进行DB映射
arp.addMapping(" animal " , AnimalModel.class );
这里我们又回到了ActiveRecordPlugin类里,它实际上有两个addMapping方法,只是参数不同。
public ActiveRecordPlugin addMapping(String tableName, String primaryKey, Class extends Model>> modelClass) {
tableList.add( new Table(tableName, primaryKey, modelClass));
return this ;
}
public ActiveRecordPlugin addMapping(String tableName, Class extends Model>> modelClass) {
tableList.add( new Table(tableName, modelClass));
return this ;
}
我们看到,第一个方法多了一个参数 String primaryKey,我的代码里用的是第二个方法。这两个方法实际上都调用了tableList.add(Table tbl)方法,我们看看tableList是什么
private List tableList = new ArrayList();
它是ActiveRecordPlugin的一个成员变量,并且是private的,那我们可以猜到,tableList保存了所有的映射关系。(ActiveRecordPlugin真是强大,后面会越来越强大~)。
第三步:创建映射关系
new Table(tableName, primaryKey, modelClass)
new Table(tableName, modelClass)
我们进去看看
public Table(String name, Class extends Model>> modelClass) {
if (StrKit.isBlank(name))
throw new IllegalArgumentException(" Table name can not be blank. " );
if (modelClass == null )
throw new IllegalArgumentException(" Model class can not be null. " );
this .name = name.trim();
this .modelClass = modelClass;
}
public Table(String name, String primaryKey, Class extends Model>> modelClass) {
if (StrKit.isBlank(name))
throw new IllegalArgumentException(" Table name can not be blank. " );
if (StrKit.isBlank(primaryKey))
throw new IllegalArgumentException(" Primary key can not be blank. " );
if (modelClass == null )
throw new IllegalArgumentException(" Model class can not be null. " );
this .name = name.trim();
setPrimaryKey(primaryKey.trim()); // this.primaryKey = primaryKey.trim();
this .modelClass = modelClass;
}
这两个方法都是为Table里的成员变量赋值,第二个方法,也就是带primaryKey参数的那个多出一行,我们看看这一行干了什么
setPrimaryKey(primaryKey.trim()); // this.primaryKey = primaryKey.trim();
void setPrimaryKey(String primaryKey) {
String[] keyArr = primaryKey.split(" , " );
if (keyArr.length > 1 ) {
if (StrKit.isBlank(keyArr[0 ]) || StrKit.isBlank(keyArr[1 ]))
throw new IllegalArgumentException(" The composite primary key can not be blank. " );
this .primaryKey = keyArr[0 ].trim();
this .secondaryKey = keyArr[1 ].trim();
}
else {
this .primaryKey = primaryKey;
}
这样的作用就是为Table下的primaryKey 和 secondaryKey赋值。
第四步:加载ActiveRecordPlugin
那么代码好像跟到这里就完事了,怎么回事?是不是跟丢了?
别忘了,ActiveRecordPlugin是在FinalConfig里的configPlugin方法加载的。那么又有谁来加载FinalConfig呢?
PS:(FinalConfig是我自己定义的类)
这儿涉及到初始化的加载了,我简单的讲一下。
public class FinalConfig extends JFinalConfig
整个JFinal的入口是web.xml的一段配置:
jfinal
class>com.jfinal.core.JFinalFilter class>
configClass
com.demo.config.FinalConfig
接着我们看到了关键的累 JFinalFilter,还是点进去看看。
public final class JFinalFilter implements Filter
这个类实现了Filter接口,那就得实现方法init(),doFilter(),destroy()方法。
我们去看init()方法:
public void init(FilterConfig filterConfig) throws ServletException {
createJFinalConfig(filterConfig.getInitParameter( " configClass " ));
if (jfinal.init(jfinalConfig, filterConfig.getServletContext()) == false )
throw new RuntimeException(" JFinal init error! " );
handler = jfinal.getHandler();
constants = Config.getConstants();
encoding = constants.getEncoding();
jfinalConfig.afterJFinalStart();
String contextPath = filterConfig.getServletContext().getContextPath();
contextPathLength = (contextPath == null || " / " .equals(contextPath) ? 0 : contextPath.length());
}
绕过其他的加载,直接看这行
if (jfinal.init(jfinalConfig, filterConfig.getServletContext()) == false )
我们看看jfinal的类型是 private static final JFinal jfinal = JFinal.me();
那么我们去JFinal类里看看它的init方法。
boolean init(JFinalConfig jfinalConfig, ServletContext servletContext) {
this .servletContext = servletContext;
this .contextPath = servletContext.getContextPath();
initPathUtil();
Config.configJFinal(jfinalConfig); // start plugin and init logger factory in this method
constants = Config.getConstants();
initActionMapping();
initHandler();
initRender();
initOreillyCos();
initI18n();
initTokenManager();
return true ;
看这行,下面这行主要是通过Config来加载暴露给程序员的核心文件,JFinalConfig的子类FinalConfig。
Config.configJFinal(jfinalConfig); // start plugin and init logger factory in this method
再点进去
* Config order: constant, route, plugin, interceptor, handler
*/
tatic void configJFinal(JFinalConfig jfinalConfig) {
jfinalConfig.configConstant(constants); initLoggerFactory();
jfinalConfig.configRoute(routes);
jfinalConfig.configPlugin(plugins); startPlugins(); // very important!!!
jfinalConfig.configInterceptor(interceptors);
jfinalConfig.configHandler(handlers);
这段代码实际上有个地方特别坑!就是
jfinalConfig.configPlugin(plugins); startPlugins(); // very important!!!
这行代码一共做了两件事,第一件事是jfinalConfig.configPlugin(plugins);来加载插件。还记得我们之前写的FinalConfig里的configPlugin(Plugins me) 方法吗?
/* *
* Config plugin
* 配置插件
* JFinal有自己独创的 DB + ActiveRecord模式
* 此处需要导入ActiveRecord插件
*/
@Override
public void configPlugin(Plugins me) {
// 读取db配置文件
loadPropertyFile(" db.properties " );
// 采用c3p0数据源
C3p0Plugin c3p0Plugin = new C3p0Plugin(getProperty(" jdbcUrl " ),getProperty(" user " ), getProperty(" password " ));
me.add(c3p0Plugin);
// 采用DB+ActiveRecord模式
ActiveRecordPlugin arp = new ActiveRecordPlugin(c3p0Plugin);
me.add(arp);
// 进行DB映射
arp.addMapping(" animal " , AnimalModel.class );
}
它实际上就是通过me.add来加载插件,通过Config的 private static final Plugins plugins = new Plugins(); 来装载。 第二件事就是 发现没有,后面的startPlugins()不是注释!是一个方法,这块实在太坑了,恰巧,这就是我们要找到的地方。
这个方法的代码有点长,但因为很重要,我不得不都贴出来。
private static void startPlugins() {
List pluginList = plugins.getPluginList();
if (pluginList != null ) {
for (IPlugin plugin : pluginList) {
try {
// process ActiveRecordPlugin devMode
if (plugin instanceof com.jfinal.plugin.activerecord.ActiveRecordPlugin) {
com.jfinal.plugin.activerecord.ActiveRecordPlugin arp =
(com.jfinal.plugin.activerecord.ActiveRecordPlugin)plugin;
if (arp.getDevMode() == null )
arp.setDevMode(constants.getDevMode());
}
boolean success = plugin.start();
if (!success) {
String message = " Plugin start error: " + plugin.getClass().getName();
log.error(message);
throw new RuntimeException(message);
}
}
catch (Exception e) {
String message =
" Plugin start error: " + plugin.getClass().getName() + " . \n " + e.getMessage();
log.error(message, e);
throw new RuntimeException(message, e);
}
}
}
}
上面这个方法一共有两个地方要注意一下,
for (IPlugin plugin : pluginList) {
上面这行是循环所有的插件,并且启动插件的start()方法。
那么,我们中有一个插件记不记得是ActiveRecordPlugin的实例?那么
boolean success = plugin.start();
这行代码就会执行ActiveRecordPlugin下的start()代码。终于绕回来了!!红军二万五千里长征,为了证明这个调用,我写了多少字....
那么我们看ActiveRecordPlugin下的start()方法吧,实际上这个start()方法是因为实现了IPlugin接口里的start()方法。
public boolean start() {
if (isStarted)
return true ;
if (dataSourceProvider != null )
dataSource = dataSourceProvider.getDataSource();
if (dataSource == null )
throw new RuntimeException(" ActiveRecord start error:
ActiveRecordPlugin need DataSource or DataSourceProvider" );
if (config == null )
config = new Config(configName, dataSource, dialect,
showSql, devMode, transactionLevel, containerFactory, cache);
DbKit.addConfig(config);
boolean succeed = TableBuilder.build(tableList, config);
if (succeed) {
Db.init();
isStarted = true ;
}
return succeed;
}
我们直接看与DB映射有关的代码,首先是取得dataSource,dataSourceProvider这个忘了没,忘了就翻到最前面,第一步讲的。
config = new Config(configName, dataSource, dialect, showSql, devMode, transactionLevel, containerFactory, cache);
这行代码中的dataSource 在插件里配置的C3P0数据源。这里的Config与前面加载FinalConfig的可不是一个啊,千万别看错了,这个是DB的 com.jfinal.plugin.activerecord.Config。
第五步:TableBuilder
来自ActiveRecordPlugin.java
boolean succeed = TableBuilder.build(tableList, config);
static boolean build(List tableList, Config config) {
Table temp = null ;
Connection conn = null ;
try {
conn = config.dataSource.getConnection();
TableMapping tableMapping = TableMapping.me();
for (Table table : tableList) {
temp = table;
doBuild(table, conn, config);
tableMapping.putTable(table);
DbKit.addModelToConfigMapping(table.getModelClass(), config);
}
return true ;
} catch (Exception e) {
if (temp != null )
System.err.println( " Can not create Table object,
maybe the table " + temp.getName() + " is not exists." );
throw new ActiveRecordException(e);
}
finally {
config.close(conn);
}
}
这里循环所有的tableList,对每个Table对象进行建表。那么我们先看看Table是用什么来存储数据库映射关系的,相信大家都能猜到是Map了。
public class Table {
private String name;
private String primaryKey;
private String secondaryKey = null ;
private Map> columnTypeMap; // config.containerFactory.getAttrsMap();
private Class extends Model>> modelClass;
columnTypeMap是关键字段,暂且记下来。
下面我们还是回到TableBuilder里的doBuild(table, conn, config);方法。
这个才是DB映射的关键,我其实直接讲这一个类就可以的......这个方法代码实在太多了,我贴部分代码做讲解吧。
那么第六步:doBuild详解。
这块有点类,我直接在代码里写注释吧:
@SuppressWarnings(" unchecked " )
private static void doBuild(Table table, Connection conn, Config config) throws SQLException {
// 初始化 Table 里的columnTypeMap字段。
table.setColumnTypeMap(config.containerFactory.getAttrsMap());
// 取得主键,如果取不到的话,默认设置"id"。
// 记不记得最开始的两个同名不同参的方法 addMapping(...),
在这才体现出后续处理的不同。
if (table.getPrimaryKey() == null )
table.setPrimaryKey(config.dialect.getDefaultPrimaryKey());
// 此处如果没有设置方言,则默认 Dialect dialect = new MysqlDialect(); Mysql的方言。
// sql为"select * from `" + tableName + "` where 1 = 2";
String sql = config.dialect.forTableBuilderDoBuild(table.getName());
Statement stm = conn.createStatement();
ResultSet rs = stm.executeQuery(sql);
// 取得个字段的信息
ResultSetMetaData rsmd = rs.getMetaData();
// 匹配映射
for (int i=1 ; i<=rsmd.getColumnCount(); i++) {
String colName = rsmd.getColumnName(i);
String colClassName = rsmd.getColumnClassName(i);
if (" java.lang.String " .equals(colClassName)) {
// varchar, char, enum, set, text, tinytext, mediumtext, longtext
table.setColumnType(colName, String.class );
}
else if (" java.lang.Integer " .equals(colClassName)) {
// int, integer, tinyint, smallint, mediumint
table.setColumnType(colName, Integer.class );
}
else if (" java.lang.Long " .equals(colClassName)) {
// bigint
table.setColumnType(colName, Long.class );
}
// else if ("java.util.Date".equals(colClassName)) {
// java.util.Data can not be returned
// java.sql.Date, java.sql.Time,
java.sql.Timestamp all extends java.util.Data so getDate can return the three types data
// result.addInfo(colName, java.util.Date.class);
// }
else if (" java.sql.Date " .equals(colClassName)) {
// date, year
table.setColumnType(colName, java.sql.Date.class );
}
else if (" java.lang.Double " .equals(colClassName)) {
// real, double
table.setColumnType(colName, Double.class );
}
else if (" java.lang.Float " .equals(colClassName)) {
// float
table.setColumnType(colName, Float.class );
}
else if (" java.lang.Boolean " .equals(colClassName)) {
// bit
table.setColumnType(colName, Boolean.class );
}
else if (" java.sql.Time " .equals(colClassName)) {
// time
table.setColumnType(colName, java.sql.Time.class );
}
else if (" java.sql.Timestamp " .equals(colClassName)) {
// timestamp, datetime
table.setColumnType(colName, java.sql.Timestamp.class );
}
else if (" java.math.BigDecimal " .equals(colClassName)) {
// decimal, numeric
table.setColumnType(colName, java.math.BigDecimal.class );
}
else if (" [B " .equals(colClassName)) {
// binary, varbinary, tinyblob, blob, mediumblob, longblob
// qjd project: print_info.content varbinary(61800);
table.setColumnType(colName, byte [].class );
}
else {
int type = rsmd.getColumnType(i);
if (type == Types.BLOB) {
table.setColumnType(colName, byte [].class );
}
else if (type == Types.CLOB || type == Types.NCLOB) {
table.setColumnType(colName, String. class );
}
else {
table.setColumnType(colName, String. class );
}
// core.TypeConverter
// throw new RuntimeException
(" You've got new type to mapping. Please add code in " + TableBuilder.class .getName()
+ " . The ColumnClassName can't be mapped: " + colClassName);
}
}
rs.close();
stm.close();
}
这里巧妙的运用了 where 1=2的无检索条件结果,通过ResultSetMetaData rsmd = rs.getMetaData(); 导出了DB模型,这招确实漂亮。之前我还冥思苦相,他是怎么做的呢,看着此处源码,茅塞顿开。
接着,把编辑好的Table实例,放到TableMapping的成员变量 Model>>, Table> modelToTableMap 里去,TableMapping是单例的。
private final Map>, Table> modelToTableMap=
new HashMap>, Table>();
public void putTable(Table table) {
modelToTableMap.put(table.getModelClass(), table);
}
这样,所有的映射关系就都存在TableMapping的modelToTableMap
tableMapping.putTable(table);
再将modelToConfig都放入DbKit.modelToConfig里。
DbKit.addModelToConfigMapping(table.getModelClass(), config);
第七步,使用
Model里的save方法举例:
/* *
* Save model.
*/
public boolean save() {
Config config = getConfig();
Table table = getTable();
StringBuilder sql = new StringBuilder();
List paras = new ArrayList();
config.dialect.forModelSave(table, attrs, sql, paras);
// if (paras.size() == 0) return false;
// The sql "insert into tableName() values()" works fine, so delete this line
// --------
Connection conn = null ;
PreparedStatement pst = null ;
int result = 0 ;
try {
conn = config.getConnection();
if (config.dialect.isOracle())
pst = conn.prepareStatement(sql.toString(),
new String[]{table.getPrimaryKey()});
else
pst = conn.prepareStatement(sql.toString(),
Statement.RETURN_GENERATED_KEYS);
config.dialect.fillStatement(pst, paras);
result = pst.executeUpdate();
getGeneratedKey(pst, table);
getModifyFlag().clear();
return result >= 1 ;
} catch (Exception e) {
throw new ActiveRecordException(e);
} finally {
config.close(pst, conn);
}
}
Config config = getConfig();
上面这行就是调用DbKit的方法,取得DB配置。
public static Config getConfig(Class extends Model> modelClass) {
return modelToConfig.get (modelClass);
}
下面这段代码是去单例的TableMapping里取得表的具体信息。
Table table = getTable();
private Table getTable() {
return TableMapping.me().getTable(getClass());
}
转载于:https://www.cnblogs.com/visec479/p/4087021.html
你可能感兴趣的:(设计模式,面试,web.xml)
RabbitMQ常见面试题及解析
chi_666
面试 RabbitMQ 面试
1、什么是RabbitMQ?RabbitMQ是一个开源的消息队列系统,它实现了高级消息队列协议(AMQP)。它允许不同的应用程序之间进行异步通信,通过将消息发送到队列中,让消费者从队列中获取消息并进行处理,从而实现解耦、异步和削峰填谷等功能。2、核心组件与流程**Producer:**发送消息的应用。**Exchange:**接收消息并路由到队列(类型:Direct,Fanout,Topic,He
精挑20题:MySQL 8.0高频面试题深度解析——掌握核心知识点、新特性和优化技巧
dblens 数据库管理和开发工具
mysql mysql 数据库 面试
1.MySQL8.0中,为什么查询缓存被移除?答案:原因:查询缓存对频繁更新的表效果差,任何对该表的写操作都会清空所有相关缓存,导致缓存命中率低,反而增加开销。替代方案:使用应用层缓存(如Redis)。优化查询和索引,减少对缓存的依赖。MySQL8.0改进:通过索引优化、并行查询等提升性能,弥补查询缓存缺失的影响。2.InnoDB的行锁和表锁分别在什么场景下使用?答案:行锁:高并发场景下更新或查询
Redis高频面试题解析干货,结合核心原理、高频考点和回答技巧
dblens 数据库管理和开发工具
redis redis 数据库 缓存
一、Redis核心数据结构与实战场景高频问题:Redis有哪些数据结构?分别适合什么场景?回答模板:基础结构(必答):String(缓存、计数器)、Hash(对象存储)、List(队列、栈)、Set(标签、去重)、ZSet(排行榜)扩展加分:Bitmaps(日活统计)、HyperLogLog(UV去重)、GEO(地理位置)场景举例(体现实战能力):例1:用ZSet实现电商销量排行榜,ZINCRBY
【面试场景题-你知道readTimeOutException,会引发oom异常吗】
F_windy
java 面试
今天面试,我讲一个oom的场景。大致是这样:因为我们有一个需要调用第三方接口的http请求,然后因为线程池配置不合理,并且超时时间设置过长,导致线程堆积,最终oom异常。我觉得这个很好理解,然后,面试官一直问,我好像没有讲很清楚。他也有点呆,问我进阻塞队列的线程会运行吗?怎么就oom了?我说,大哥,线程创建出来就要占用内存了呀。他好像还是不懂。然后总结了一下。当系统出现readtimeout异常时
【附JS、Python、C++题解】Leetcode面试150题(7)
moz与京
leetcode整理 javascript python c++
一、题目167.两数之和II-输入有序数组给你一个下标从1开始的整数数组numbers,该数组已按非递减顺序排列,请你从数组中找出满足相加之和等于目标数target的两个数。如果设这两个数分别是numbers[index1]和numbers[index2],则1targetIndex(vectornums,inttarget){intlength=nums.size();if(length<2){
编程-设计模式 30:拦截过滤器模式(Interceptor Filter Pattern)
漆黑的莫莫
编程设计模式 J2EE设计模式 设计模式
设计模式30:拦截过滤器模式(InterceptorFilterPattern)定义与目的定义:拦截过滤器模式是一种用于Web应用程序中的模式,它提供了一种机制来拦截请求和响应,并在它们到达目标处理程序之前执行一些预处理任务,在响应返回客户端之前执行一些后处理任务。目的:该模式的主要目的是通过将请求处理逻辑与请求的预处理和后处理任务分离,提高应用程序的模块化程度和可维护性。实现示例假设我们有一个简
C++基础匿名对象,友元和常成员(const)
没有百宝袋的哆啦A梦
c++ java jvm
目录学习内容:1.匿名对象2.友元2.1友元的引入2.2友元函数2.3友元类2.4友元的总结3.常成员(const)3.1常成员的引入3.2常成员函数3.3常对象3.4mutable关键字3.5常函数3.6关于C/C++中const的使用(面试题)学习内容:1.匿名对象1>所谓匿名对象,就是没有名字的对象,生命周期只在当前语句内,所以可以理解成时一个将亡值2>定义格式:直接调用类的构造函数3>使用
工厂函数详解:概念、目的与作用
漫谈网络
网络技术进阶通途 工厂函数 mininet sdn nfv 网络
一、什么是工厂函数?工厂函数(FactoryFunction)是一种设计模式,其核心是通过一个函数来创建并返回对象,而不是直接使用new或构造函数实例化对象。它封装了对象的创建过程,使代码更灵活、可维护。二、工厂函数的目的与作用目的作用解耦对象创建逻辑将对象的创建与使用分离,调用者无需关心对象的具体实现细节。延迟实例化仅在需要时创建对象,避免资源浪费(如内存、CPU)。支持动态参数根据输入参数返回
MySQL 8.0 特性的高频面试题及核心知识点
dblens 数据库管理和开发工具
mysql mysql 数据库 面试题
1.索引原理与MySQL8.0新特性答案:自适应哈希索引:MySQL8.0自动在频繁查询的索引上构建哈希索引,加速等值查询(如WHEREid=1)。全文索引优化:支持布尔模式(MATCH()AGAINST())和自然语言模式,且索引更新更高效。InnoDB页压缩:支持ZSTD压缩算法,减少存储空间和I/O开销。虚拟列索引:可对虚拟列(ComputedColumns)创建索引,减少存储冗余。2.事务
推测未来Agentic形态:Dynamic Cognitive Contextual Agent with Reinforcement Learning (DCCA-RL)
weixin_40941102
语言模型
在AIAgent设计模式领域,我们见证了从简单的ReAct到复杂的LATS的演进,这些模式通过反思、工具使用、规划和多代理协作,极大地提升了AI的自主性和智能性。然而,随着任务复杂度和动态性需求的增加,现有模式逐渐显现出局限性——多Agent协作带来的联合误差和单Agent设计的适应性不足。为此,我们基于对现有模式的全面分析,提出了一个更先进的单Agent框架:DynamicCognitiveCo
JDK8 Stream 数据流效率分析,Java开发你需要了解的那些事
气质大叔
程序员 后端 面试 java
此外还有一系列特化流,如IntStream,LongStream,DoubleStream等),Java8引入的的Stream主要用于取代部分Collection的操作,每个流代表一个值序列,流提供一系列常用的聚集操作,可以便捷的在它上面进行各种运算。集合类库也提供了便捷的方式使我们可以以操作流的方式使用集合、数组以及其它数据结构;作为阅读福利,小编也整理了一些Java学习笔记(包含面试真题+脑图
React中useEffect和useLayoutEffect的区别
CreatorRay
前端 面试 react react.js 前端 面试
在最近一次面试中被问到,我印象中好像从来没用过useLayoutEffect,就没答上来。但是看名字应该是跟布局相关的,而且跟useEffect会有类似的作用。在React中,useEffect和useLayoutEffect都是用于处理副作用的Hooks,但它们的执行时机和对渲染流程的影响有显著区别。以下是两者的核心差异及使用场景:公众号:Code程序人生,个人网站:https://creato
深入解析:C# 中 `Task.Delay` 与 `Thread.Sleep` 的对比与实战
墨夶
C#学习资料1 c# 开发语言
嘿,小伙伴们!今天我们要一起深入探讨C#中的Task.Delay和Thread.Sleep。想象一下,你正在开发一个需要处理异步操作的应用程序,如何有效地管理线程和延迟执行任务呢?别急,让我们通过这篇文章来详细解析Task.Delay和Thread.Sleep的区别,并涵盖以下内容:基本概念Thread.Sleep的用法Task.Delay的用法对比分析实战示例注意事项与最佳实践常见面试题及答案正
计算机网络笔记、面试八股(二)—— HTTP协议
Your_Raymond
计算机网络 http 计算机网络 面试
本章目录2.HTTP协议2.1HTTP协议简介2.2HTTP协议的优点2.3HTTP协议的缺点2.4HTTP协议属于哪一层2.5HTTP通信过程2.6常见请求方法2.7GET和POST的区别2.8请求报文与响应报文2.8.1HTTP请求报文2.8.2HTTP响应报文2.9响应状态码2.10HTTP1.0和1.1的区别2.10.1长连接2.10.2错误响应码2.10.3缓存处理2.10.4带宽的优化
设计模式-责任链模式
小九没绝活
设计模式 设计模式 责任链模式 java
核心思想责任链模式通过将多个处理对象(Handler)连接成一条链,允许请求在链上传递,直到被某个对象处理或链终止。核心目标是解耦请求发送者与接收者,让多个对象都有机会处理请求,增强系统的灵活性和可扩展性。模式结构角色职责抽象处理者定义处理请求的接口(Handler),通常包含设置下一个处理者的方法具体处理者实现抽象处理者接口,判断是否能处理请求,否则传递给下一个处理者客户端创建处理链,并向链的头
项目经理面试全攻略:从底层能力拆解到高通过率话术
在竞争激烈的职场中,项目经理岗位的面试堪称“综合能力大考”——既要展现系统化的方法论,又要传递真实的领导力,还要让考官相信你能在复杂环境中推动结果落地。据PMI(美国项目管理协会)调查,82%的优秀项目经理在面试中能清晰呈现“业务价值-团队协作-风险控制”的三角能力模型。本文从能力拆解、面试准备、实战话术三个维度,揭秘项目经理面试通关法则。一、项目经理面试的四大核心能力雷达图面试官通过以下维度评估
当我被面试官追问如何优化慢SQL时,我悟了这些底层逻辑
mysql数据库程序员后端
当我被面试官追问如何优化慢SQL时,我悟了这些底层逻辑去年面试字节跳动时,我遇到了一个至今印象深刻的场景:面试官在白板上写了一条包含三表JOIN且带有子查询的SQL,淡淡地说"请分析这条SQL的性能问题"。当时我的后背瞬间绷直——这道题考察的不仅是SQL优化技巧,更是对数据库底层原理的深刻理解。一、面试官到底在考察什么?实战经验:是否真正处理过线上慢查询问题,能否结合业务场景分析知识体系:从索引设
C++ 结构型设计模式
十七12138
C++ c++ 设计模式
C++设计模式自己理解整理笔记结构型-适配器模式适配器模式(AdapterPattern)是一种结构型设计模式,它的主要作用是将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。适配器模式主要有两种实现方式:类适配器模式和对象适配器模式。类适配器类适配器通过多重继承实现,这种方式利用了继承优点直接调用:由于适配器类继承了被适配类,所以可以直接调用被适
python面试题详解
__wishing__
python
十道经典面试题(python)1.一行代码实现累加1-100之和print(sum(range(1,101)))输出结果:5050分析:利用sum函数进行累加。range控制序列。2.一行代码实现列表去重#声明需要去重的列表list1=[1,1,2,2,3,3,4,4]list1=list(set(list1))</
2025美团最新面试题—Java程序减少GC的设计
程序员共鸣
java jvm 开发语言
1.对象复用与池化线程局部变量:通过ThreadLocal缓存线程私有对象,避免竞争。可变对象:优先使用可修改对象(如StringBuilder代替String拼接)。2.减少对象创建避免隐式装箱:使用基本类型(int而非Integer)。优化循环:避免在循环内创建临时对象。静态不可变对象:将常量声明为staticfinal(如配置参数)。3.数据结构优化预分配容量:初始化集合时指定合理大小(如A
Webpack常见面试题总结
xiangzhihong8
React Native 前端 webpack 前端 javascript
一、谈谈你对Webpack的理解1.1背景Webpack的目标是实现前端项目的模块化,从而更高效地管理和维护项目中的每一个资源。在早期的前端项目中,我们通过文件划分的形式来实现模块化,也就是将每个功能及其相关状态数据各自单独放到不同的JS文件中。约定每个文件是一个独立的模块,然后再将这些js文件引入到页面,一个script标签对应一个模块,然后再调用模块化的成员。比如:但这种模块化开发的弊端也十分
初级面试题:数据类型面试题大揭秘
佩奇的技术笔记
Java面试小册 java 开发语言
一、引言在Java开发的面试中,数据类型相关的问题经常出现。面试官通过这些问题考察候选人对Java基础的理解程度以及在实际开发中对数据类型的运用能力。本文将深入剖析常见的数据类型面试题,帮助读者全面掌握这些知识点。二、基本数据类型与引用数据类型面试题:int和Integer的区别是什么?答案:int是基本数据类型,占用4个字节内存,直接存储数值;Integer是int对应的引用数据类型,即包装类,
前端开发:Webpack的使用总结
三掌柜666
web前端知识汇总 webpack 前端 javascript
前言在前端开发过程中,尤其是现在前端框架的频繁使用的当下,作为前端开发者想必对于Webpack并不陌生,尤其是在使用Vue框架做前端开发的时候,打包时候必用Webpack。还有就是在前端求职面试的时候,Webpack相关的知识点也是面试官必定考察的,那么本篇博文就来分享一下关于Webpack使用相关的知识点,记录下来,方便后期查阅使用。Webpack概念Webpack其实是一个前端资源加载/打包工
金三银四快过去一半了,是时候加把劲了
后端go找工作面试
从复旦春招会的15000+岗位争夺战,到AI算法岗年薪百万的“神仙打架”,再到游戏行业20:1的残酷竞争比,今年的金三银四像极了《三体》里的黑暗森林:机会看似遍地,但稍有不慎就成了别人的“背景板”。但现实真的是“投晚了就凉了”吗?数据告诉你真相:智联研究院统计显示,算法工程师、机器人算法工程师等岗位需求同比激增44%,而中小企业的“捡漏窗口”才刚开启。这半个月,我整理了20+场面试实录(含小鹅通、
2025React岗位前端面试题180道及其答案解析,看完稳了,万字长文,持续更新....
祈澈菇凉
前端
1.什么是React?它的主要特点是什么?答案解析:React是一个用于构建用户界面的JavaScript库,主要用于构建单页应用。其主要特点包括:组件化:React应用由多个可重用的组件组成,便于管理和维护。虚拟DOM:React使用虚拟DOM提高性能,通过最小化实际DOM操作来优化渲染过程。单向数据流:数据在组件之间以单向流动的方式传递,简化了数据管理和调试。声明式编程:React允许开发者以
工厂方法模式、简单工厂模式与抽象工厂模式的对比
智想天开
工厂方法模式 简单工厂模式 抽象工厂模式
原文地址:工厂方法模式、简单工厂模式与抽象工厂模式的对比更多内容请关注:深入思考与解读设计模式引言在面向对象设计中,工厂模式是一种常用的创建型设计模式,帮助我们在不直接暴露对象创建逻辑的情况下,生成对象。你是否曾经在开发过程中遇到过对象创建的需求?你是否觉得对象的创建过程可能随着系统的复杂性增加而变得越来越繁琐?如果我们有一种方法能够简化和统一对象创建的过程,是否能提高代码的灵活性和可维护性?工厂
MySQL 面试题
你曾经是少年
mysql 数据库
1.数据库基础问题:请解释数据库(DB)、数据库管理系统(DBMS)、SQL三者的区别。参考答案:DB:存储数据的结构化仓库DBMS:管理数据库的软件(如MySQL、Oracle)SQL:操作关系型数据库的标准化语言2.SQL分类问题:SQL分为哪几类?分别写出对应的关键字(至少3个)。参考答案:DDL:CREATE/DROP/ALTERDML:INSERT/UPDATE/DELETEDQL:SE
【前端网络深潜行者】信息化人员必备知识&面试宝典:TCP连接中断,客户端突然“玩失踪”怎么办?
DTcode7
IT信息技术相关 # 信息化技能面试宝典 HTML5 前端 javascript 前端三大核心 JS
【前端网络深潜行者】信息化人员必备知识&面试宝典:TCP连接中断,客户端突然“玩失踪”怎么办?TCP的忠诚卫士:保活与重传保活机制(Keepalive)超时重传与超时前端策略:优雅的应对与重连案例一:心跳检测案例二:断线重连逻辑安全与性能考量实战经验之谈排错思路结语与探讨在网络通信的迷宫中,TCP/IP协议犹如稳固的桥梁,承载着数据的往来。然而,当客户端这个“信使”突然玩起了失踪”,我们如何确保这
Java设计模式之代理模式
飞翔中文网
Java java 设计模式
概念和作用代理模式是一种结构型设计模式,它允许为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介作用,可以在目标对象执行某些操作前后添加额外的功能。使用场景1.访问控制:根据用户权限决定是否允许访问目标对象。2.日志记录:在访问目标对象前后记录日志信息。3.性能监控:测量目标对象方法的执行时间。4.延迟加载:按需加载资源,避免过早占用内存。举例静态代理静态代理在编
Vue.js的watch监听
阿珊和她的猫
vue.js 前端 javascript
前端开发工程师、技术日更博主、已过CET6阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1牛客高级专题作者、打造专栏《前端面试必备》、《2024面试高频手撕题》、《前端求职突破计划》蓝桥云课签约作者、上架课程《Vue.js和Egg.js开发企业级健康管理项目》、《带你从入门到实战全面掌握uni-app》文章目录引言`watch`选项的基本概念`watch`选项的基本语法`watch
HQL之投影查询
归来朝歌
HQL Hibernate 查询语句 投影查询
在HQL查询中,常常面临这样一个场景,对于多表查询,是要将一个表的对象查出来还是要只需要每个表中的几个字段,最后放在一起显示?
针对上面的场景,如果需要将一个对象查出来:
HQL语句写“from 对象”即可
Session session = HibernateUtil.openSession();
Spring整合redis
bylijinnan
redis
pom.xml
<dependencies>
<!-- Spring Data - Redis Library -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redi
org.hibernate.NonUniqueResultException: query did not return a unique result: 2
0624chenhong
Hibernate
参考:http://blog.csdn.net/qingfeilee/article/details/7052736
org.hibernate.NonUniqueResultException: query did not return a unique result: 2
在项目中出现了org.hiber
android动画效果
不懂事的小屁孩
android动画
前几天弄alertdialog和popupwindow的时候,用到了android的动画效果,今天专门研究了一下关于android的动画效果,列出来,方便以后使用。
Android 平台提供了两类动画。 一类是Tween动画,就是对场景里的对象不断的进行图像变化来产生动画效果(旋转、平移、放缩和渐变)。
第二类就是 Frame动画,即顺序的播放事先做好的图像,与gif图片原理类似。
js delete 删除机理以及它的内存泄露问题的解决方案
换个号韩国红果果
JavaScript
delete删除属性时只是解除了属性与对象的绑定,故当属性值为一个对象时,删除时会造成内存泄露 (其实还未删除)
举例:
var person={name:{firstname:'bob'}}
var p=person.name
delete person.name
p.firstname -->'bob'
// 依然可以访问p.firstname,存在内存泄露
Oracle将零干预分析加入网络即服务计划
蓝儿唯美
oracle
由Oracle通信技术部门主导的演示项目并没有在本月较早前法国南斯举行的行业集团TM论坛大会中获得嘉奖。但是,Oracle通信官员解雇致力于打造一个支持零干预分配和编制功能的网络即服务(NaaS)平台,帮助企业以更灵活和更适合云的方式实现通信服务提供商(CSP)的连接产品。这个Oracle主导的项目属于TM Forum Live!活动上展示的Catalyst计划的19个项目之一。Catalyst计
spring学习——springmvc(二)
a-john
springMVC
Spring MVC提供了非常方便的文件上传功能。
1,配置Spring支持文件上传:
DispatcherServlet本身并不知道如何处理multipart的表单数据,需要一个multipart解析器把POST请求的multipart数据中抽取出来,这样DispatcherServlet就能将其传递给我们的控制器了。为了在Spring中注册multipart解析器,需要声明一个实现了Mul
POJ-2828-Buy Tickets
aijuans
ACM_POJ
POJ-2828-Buy Tickets
http://poj.org/problem?id=2828
线段树,逆序插入
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>using namespace std;#define N 200010struct
Java Ant build.xml详解
asia007
build.xml
1,什么是antant是构建工具2,什么是构建概念到处可查到,形象来说,你要把代码从某个地方拿来,编译,再拷贝到某个地方去等等操作,当然不仅与此,但是主要用来干这个3,ant的好处跨平台 --因为ant是使用java实现的,所以它跨平台使用简单--与ant的兄弟make比起来语法清晰--同样是和make相比功能强大--ant能做的事情很多,可能你用了很久,你仍然不知道它能有
android按钮监听器的四种技术
百合不是茶
android xml配置 监听器 实现接口
android开发中经常会用到各种各样的监听器,android监听器的写法与java又有不同的地方;
1,activity中使用内部类实现接口 ,创建内部类实例 使用add方法 与java类似
创建监听器的实例
myLis lis = new myLis();
使用add方法给按钮添加监听器
软件架构师不等同于资深程序员
bijian1013
程序员 架构师 架构设计
本文的作者Armel Nene是ETAPIX Global公司的首席架构师,他居住在伦敦,他参与过的开源项目包括 Apache Lucene,,Apache Nutch, Liferay 和 Pentaho等。
如今很多的公司
TeamForge Wiki Syntax & CollabNet User Information Center
sunjing
TeamForge How do Attachement Anchor Wiki Syntax
the CollabNet user information center http://help.collab.net/
How do I create a new Wiki page?
A CollabNet TeamForge project can have any number of Wiki pages. All Wiki pages are linked, and
【Redis四】Redis数据类型
bit1129
redis
概述
Redis是一个高性能的数据结构服务器,称之为数据结构服务器的原因是,它提供了丰富的数据类型以满足不同的应用场景,本文对Redis的数据类型以及对这些类型可能的操作进行总结。
Redis常用的数据类型包括string、set、list、hash以及sorted set.Redis本身是K/V系统,这里的数据类型指的是value的类型,而不是key的类型,key的类型只有一种即string
SSH2整合-附源码
白糖_
eclipse spring tomcat Hibernate Google
今天用eclipse终于整合出了struts2+hibernate+spring框架。
我创建的是tomcat项目,需要有tomcat插件。导入项目以后,鼠标右键选择属性,然后再找到“tomcat”项,勾选一下“Is a tomcat project”即可。具体方法见源码里的jsp图片,sql也在源码里。
补充1:项目中部分jar包不是最新版的,可能导
[转]开源项目代码的学习方法
braveCS
学习方法
转自:
http://blog.sina.com.cn/s/blog_693458530100lk5m.html
http://www.cnblogs.com/west-link/archive/2011/06/07/2074466.html
1)阅读features。以此来搞清楚该项目有哪些特性2)思考。想想如果自己来做有这些features的项目该如何构架3)下载并安装d
编程之美-子数组的最大和(二维)
bylijinnan
编程之美
package beautyOfCoding;
import java.util.Arrays;
import java.util.Random;
public class MaxSubArraySum2 {
/**
* 编程之美 子数组之和的最大值(二维)
*/
private static final int ROW = 5;
private stat
读书笔记-3
chengxuyuancsdn
jquery笔记 resultMap配置 ibatis一对多配置
1、resultMap配置
2、ibatis一对多配置
3、jquery笔记
1、resultMap配置
当<select resultMap="topic_data">
<resultMap id="topic_data">必须一一对应。
(1)<resultMap class="tblTopic&q
[物理与天文]物理学新进展
comsci
如果我们必须获得某种地球上没有的矿石,才能够进行某些能量输出装置的设计和建造,而要获得这种矿石,又必须首先进行深空探测,而要进行深空探测,又必须获得这种能量输出装置,这个矛盾的循环,会导致地球联盟在与宇宙文明建立关系的时候,陷入困境
怎么办呢?
 
Oracle 11g新特性:Automatic Diagnostic Repository
daizj
oracle ADR
Oracle Database 11g的FDI(Fault Diagnosability Infrastructure)是自动化诊断方面的又一增强。
FDI的一个关键组件是自动诊断库(Automatic Diagnostic Repository-ADR)。
在oracle 11g中,alert文件的信息是以xml的文件格式存在的,另外提供了普通文本格式的alert文件。
这两份log文
简单排序:选择排序
dieslrae
选择排序
public void selectSort(int[] array){
int select;
for(int i=0;i<array.length;i++){
select = i;
for(int k=i+1;k<array.leng
C语言学习六指针的经典程序,互换两个数字
dcj3sjt126com
c
示例程序,swap_1和swap_2都是错误的,推理从1开始推到2,2没完成,推到3就完成了
# include <stdio.h>
void swap_1(int, int);
void swap_2(int *, int *);
void swap_3(int *, int *);
int main(void)
{
int a = 3;
int b =
php 5.4中php-fpm 的重启、终止操作命令
dcj3sjt126com
PHP
php 5.4中php-fpm 的重启、终止操作命令:
查看php运行目录命令:which php/usr/bin/php
查看php-fpm进程数:ps aux | grep -c php-fpm
查看运行内存/usr/bin/php -i|grep mem
重启php-fpm/etc/init.d/php-fpm restart
在phpinfo()输出内容可以看到php
线程同步工具类
shuizhaosi888
同步工具类
同步工具类包括信号量(Semaphore)、栅栏(barrier)、闭锁(CountDownLatch)
闭锁(CountDownLatch)
public class RunMain {
public long timeTasks(int nThreads, final Runnable task) throws InterruptedException {
fin
bleeding edge是什么意思
haojinghua
DI
不止一次,看到很多讲技术的文章里面出现过这个词语。今天终于弄懂了——通过朋友给的浏览软件,上了wiki。
我再一次感到,没有辞典能像WiKi一样,给出这样体贴人心、一清二楚的解释了。为了表达我对WiKi的喜爱,只好在此一一中英对照,给大家上次课。
In computer science, bleeding edge is a term that
c中实现utf8和gbk的互转
jimmee
c iconv utf8&gbk编码
#include <iconv.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
int code_c
大型分布式网站架构设计与实践
lilin530
应用服务器 搜索引擎
1.大型网站软件系统的特点?
a.高并发,大流量。
b.高可用。
c.海量数据。
d.用户分布广泛,网络情况复杂。
e.安全环境恶劣。
f.需求快速变更,发布频繁。
g.渐进式发展。
2.大型网站架构演化发展历程?
a.初始阶段的网站架构。
应用程序,数据库,文件等所有的资源都在一台服务器上。
b.应用服务器和数据服务器分离。
c.使用缓存改善网站性能。
d.使用应用
在代码中获取Android theme中的attr属性值
OliveExcel
android theme
Android的Theme是由各种attr组合而成, 每个attr对应了这个属性的一个引用, 这个引用又可以是各种东西.
在某些情况下, 我们需要获取非自定义的主题下某个属性的内容 (比如拿到系统默认的配色colorAccent), 操作方式举例一则:
int defaultColor = 0xFF000000;
int[] attrsArray = { andorid.r.
基于Zookeeper的分布式共享锁
roadrunners
zookeeper 分布式 共享锁
首先,说说我们的场景,订单服务是做成集群的,当两个以上结点同时收到一个相同订单的创建指令,这时并发就产生了,系统就会重复创建订单。等等......场景。这时,分布式共享锁就闪亮登场了。
共享锁在同一个进程中是很容易实现的,但在跨进程或者在不同Server之间就不好实现了。Zookeeper就很容易实现。具体的实现原理官网和其它网站也有翻译,这里就不在赘述了。
官
两个容易被忽略的MySQL知识
tomcat_oracle
mysql
1、varchar(5)可以存储多少个汉字,多少个字母数字? 相信有好多人应该跟我一样,对这个已经很熟悉了,根据经验我们能很快的做出决定,比如说用varchar(200)去存储url等等,但是,即使你用了很多次也很熟悉了,也有可能对上面的问题做出错误的回答。 这个问题我查了好多资料,有的人说是可以存储5个字符,2.5个汉字(每个汉字占用两个字节的话),有的人说这个要区分版本,5.0
zoj 3827 Information Entropy(水题)
阿尔萨斯
format
题目链接:zoj 3827 Information Entropy
题目大意:三种底,计算和。
解题思路:调用库函数就可以直接算了,不过要注意Pi = 0的时候,不过它题目里居然也讲了。。。limp→0+plogb(p)=0,因为p是logp的高阶。
#include <cstdio>
#include <cstring>
#include <cmath&