《spring 3.X企业应用开发实战》
1.资源范围利器:P53
?:匹配文件中的一个字符
*:匹配文件中任意字符
**:匹配多层路径
eg:classpath*:org/**/s*.xml
2.介绍beanFactory和ApplicationContext的关系 P58
3.介绍依赖注入的三种形式 P86
<<effective java>>
1.静态工厂方法代替构造器的优劣:P4
优势:
①静态工厂方法有名称
②不必每次调用的时候都创建一个新的对象
③可以根据参数的不同返回任意子类型的对象
基于接口的框架,对于客户端是不可见的,未来修改返回的对象,对客户端没有影响
④创建参数化类型实例的时候,使代码变的简洁
eg:
Map<String, List<String>> m = new HashMap<String, List<Sring>>();
修改为Map<String, List<String>> m = HashMap.newInstance();
public static <K, V> HashMap<K, V> newInstance(){
return new HashMap<K, V>();
}
劣势:
①与其他的静态方法没有任何区别,使用javadoc生成API时,没有想构造器那样被明确标识出来
②类如果不含有公有的或者受保护的构造器,就不能被子类化(使用静态工厂方法,一般就把类的构造器定义为private)
如下面的类T1就不能够被子类化
public class T1 {
private T1(){
}
public T1(String a){
}
}
2.遇到多个构造器参数时,考虑使用构建器(build) P9
重叠构造器、静态工厂方法当遇到多个参数时,会变的比较难阅读,如果没有详细的文档,容易出错,出了错,还比较难排查
javaBean的方式弥补了重叠构造器的缺点,但是它不安全
build即可以像构造器那样安全,也能像JavaBean有那么好的可读性,但是会花费一定的开销,代码比重叠构造器要冗长。因此只有在参数的多的情况,才考虑使用
public class TestBuild {
private final int a;
private final int b;
private final int c;
private final int d;
private final int e;
private final int f;
public static class Builder{
// 必须的参数
private final int a;
private final int b;
// 可选的
private int c = 0;
private int d = 0;
private int e = 0;
private int f = 0;
public Builder(int a, int b){
this.a = a;
this.b = b;
}
public Builder c(int val){
this.c = val;
return this;
}
public Builder d(int val){
this.c = val;
return this;
}
public Builder e(int val){
this.c = val;
return this;
}
public Builder f(int val){
this.c = val;
return this;
}
public TestBuild build(){
return new TestBuild(this);
}
}
private TestBuild(Builder builder){
a = builder.a;
b = builder.b;
c = builder.c;
d = builder.d;
e = builder.e;
f = builder.f;
}
}
创建对象的方式如下:
TestBuild test = new TestBuild.Builder(100, 10).c(300).e(200).build();
3.创建singleton实例 P14
有三种方法
①公有域方法(类成员的声明很清楚的表明了这个类是个singleton)
public class TestSingleton{
public static final TestSingleton instance = new TestSingleton();
private TestSingleton(){}
}
②静态工厂方法(可以在不改变API的前提下,可以改变该类是否应该为singleton的想法)
public class TestSingleton implements Serializable{
private static final TestSingleton instance = new TestSingleton();
private TestSingleton(){}
public static TestSingleton getInstance(){return instance;};
// 序列化遇到单例时,从内存中读出组装的对象破坏了单例的规则,因为反序列化时,克隆出了一个新的对象
// 当jvm从内存反序列化时,就会自动调用这个 readResolve方法来返回我们指定好的对象了, 单例规则也就得到了保证.
private Object readResolve() throws ObjectStreamException {
return instance;
}
}
③使用枚举类型
public enum TestEnum {
INSTANCE;
public void test(){
}
}
与公有域方法相近,更简洁,无常的提供序列号机制,绝对防止多次实例化
4.通过私有构造器强化不可实例化的功能 P16
这种类一般指的工具类
5.避免创建不必要的对象 P17
①
String aa = new String("123456"); // 每次调用都产生新的对象
String aa = "123456"; // 只有一个实例,可以保证,在同一台虚拟机中运行的代码,只要包含相同的字符串字面变量,该对象就会被重用
②对应同时提供静态工厂方法和构造器的不可变类,通常使用静态工厂方法避免创建不必要的对象。因为构造器每次调用都会产生新的对象
③重用那些已知不会被修改的可变对象,即对象修改为final静态域,也可以进行延迟初始化(不建议这么做,会使方法变的复杂,而且无法显著的提高性能)
④Map的keyset返回Map对象的Set视图,看起来好像每次调用keyset都会创建新的Set实例,实际上对于一个给定的Map对象,每次调用keyset都返回同样的Set实例
⑤自动装箱和拆箱(要优先使用基本数据类型,而不是装箱基本类型)
Long sum = 0L;
for(long i = 0; i < Integer.MAX_VALUE; i++){
sum += i;
}
上面这段程序就构造了2的31次方个多余的Long实例,性能大大折扣
⑥对象池不要乱用,除非池中的的对象是非常重量级的,如数据库连接池。对象池会使你的代码很乱,同时增加内存占用。
⑦保护性拷贝指的是“当你应该创建新对象的时候,请不要重用现有的对象”,是与本条想对应的。不重用对象只会影响程序的风格和性能;但是没有实施必要的保护性拷贝,将会导致潜在的错误和安全漏洞