谁打开了流,谁就应该负责关闭这个流
谁打开了流,谁就应该负责关闭这个流。 理由一 在现实系统中,打开流、关闭流的动作可能并不仅是一次open(), close()调用,可能还包括记日志、通知相关模块等附加动作,而这些动作在open/close时往往还是对称的,也就是说,在open()时做一些附加动作,在close()时可能会作一些类似的或反向的附加动作。 既然这些附加动作是对称的,那它们最好放在一个类里;反推过来,open和close调用最好也放在同一个类里。 理由二 待想。。。
谁打开了流,谁就应该负责关闭这个流。 理由一 在现实系统中,打开流、关闭流的动作可能并不仅是一次open(), close()调用,可能还包括记日志、通知相关模块等附加动作,而这些动作在open/close时往往还是对称的,也就是说,在open()时做一些附加动作,在close()时可能会作一些类似的或反向的附加动作。 既然这些附加动作是对称的,那它们最好放在一个类里;反推过来,open和close调用最好也放在同一个类里。 理由二 待想。。。
这里有个 精准的定义: http://en.wikipedia.org/wiki/Service_provider_interface spi发现机制: 1. jdk有一套以java.util.ServiceLoader为核心的机制。 ServiceLoader会从类路径查找做了相关META-INF声明的jar包,所以上层不必耦合SPI具体实现的类。 2. 其实用spring IoC搞更直观 spi跟api在语言层面的联系:有两种模式 1. spi即api,具体的类实现指定的接口。比如Tomcat的Request类实现HttpServletRequest 2. spi本身采用interface/implementation机制,接口中提供的方法直接贴近底层或者只用作工厂,不为用户所知;然后,spi接口作为api的成员变量,api在有需要时调用spi完成工作
<mvc:annotation-driven> <mvc:async-support default-timeout="3000"/> </mvc:annotation-driven> 如果不配这个东西,callable里的代码会被直接忽略
在协议栈中,上层调用下层的操作很容易,直接做方法调用就可以了;那么下层如何调用上层呢? 大家都知道,下层不能依赖上层。 搜了一下,其中一个答案是 依赖注入 + 回调: 1. 做一个虚的Handler, 上层对象实现这个handler,并注入到本层对象中 2. 当本层做完自己的事后,调用handler.handleReceive(data)将数据抛给handler(实际是丢给上层对象)
Java5+: 引用 -agentlib:jdwp=transport=dt_socket,address=localhost:9009,server=y,suspend=y Java1.4- 引用 -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=9009
Spark的登录:LoginDialog.login()方法 1. 生成一个SessionManager 2. 生成一个XMPPConnection对象 3. 然后用XMPPConnection建立连接并初始化:生成socket,并建好它的reader/writer 4. 然后调用XMPPConnection.login()方法,为了简化,先把SASL抛一边,看看smack怎么用NonSASLAuthentication来做认证 5. 会对密码作digest,避免直接传password. 作digest时会用connectionId当盐 6. 发出认证请求,服务端返回用户名 7. 最后把服务端返回的用户名更新到connection.user中, 设置connection.authenticated = true, anonymous = false 再来看看spark如何使用身份信息,以 Roster.reload()为例(刷新好友列表) 1. packetWriter.sendPacket(packet)发出packet,packet里面不会掺杂用户身份信息。 2. 服务端收到消息后,其中一步是在ClientStanzaHandler.processMessage()中执行 packet.setFrom(session.getAddress()),把身份消息塞入Packet 引用 <iq id="psg6P-8" type="get" from="kent@someServer/Spark 2.6.3"> <query xmlns="jabber:iq:roster"/> </iq> 也就是说服务端直接把用户的身份信息放在服务端的mina session对象里,要用时再从session里把用户信息取出来
为什么在调用栈的较深处抛异常会导致性能问题 ? 这是因为 构建Exception对象时会去取一下当前调用栈的快照(Throwable.fillInStackTrace()),这个操作比较耗时。 栈越深,操作就越耗时。 怎么解决这个问题? 1. 避免滥用Exception作为Flow-Control的工具。 比如判断类型时可以用 instanceof ,而不必强转+捕捉ClassCastException. 2. 重用Exception对象。 这样总体上只需要取一次栈的快照。 3. 覆盖fillInStackTrace()方法,使它变成空方法;也就是说, 不生成快照。
在32位机器中,由于long, double数据较长,跨多个地址;导致这个long, double的读写不是原子的。 所以,对long, double的读写操作,在必须情况理应该加锁。 在64位机上,理论上long,double是原子的;但由于指针压缩技术,long,double等仍可能跨地址存储,所以对它们的读写操作可能仍不是原子的。
headers.add(“Access-Control-Allow-Origin”, “*”); headers.add(“Access-Control-Allow-Methods”, “GET, POST, PUT, DELETE, OPTIONS, HEAD”); headers.add( “Access-Control-Allow-Headers”, “Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, Authorization”); headers.add(“Access-Control-Expose-Headers”, “WWW-Authenticate”);
Class是哪种Class ? clazz.isPrimitive(); //是否primitive type //是否为primitive type的封装类?看看它在不在下面的map里(这个map节选自spring的ClassUtils.java) primitiveWrapperTypeMap.put(Boolean.class, boolean.class); primitiveWrapperTypeMap.put(Byte.class, byte.class); primitiveWrapperTypeMap.put(Character.class, char.class); primitiveWrapperTypeMap.put(Double.class, double.class); primitiveWrapperTypeMap.put(Float.class, float.class); primitiveWrapperTypeMap.put(Integer.class, int.class); primitiveWrapperTypeMap.put(Long.class, long.class); primitiveWrapperTypeMap.put(Short.class, short.class); clazz.isArray(); //是否为数组类型 拿到的是java.lang.reflect.Type类型,它是哪种Type ? if (javaReflectType instanceof ParameterizedType); //是否为泛型 if (javaReflectType instanceof Class) //是否为类 是哪种泛型 ParameterizedType pt = (ParameterizedType) javaReflectType; Type rawType = pt.getRawType(); //尖括号前面的类型,如List<String>中的List //Collection<SomeClass> if (Collection.class.isAssignableFrom(rawClass)) { Type type = …