一直想專門寫個Spring源碼的博客,工做了,能夠全身性的投入到互聯網行業中。雖然加班很嚴重,可是依然很開心。趁着凌晨有時間,總結總結。
首先spring,相信你們都很熟悉了。
一、輕量級 零配置,API使用簡單
二、面向Bean 只須要編寫普通的Bean(一個Bean表明一個對象)
三、鬆耦合 充分利用AOP思想 )(各自能夠獨立開發,而後整合起來運行)
四、萬能膠 與主流框架無縫集成 (Mybatis dubbo等等 )
五、設計模式 將Java中經典的設計模式運用的淋漓盡致
Spring解決企業級應用開發的負責設計,簡化開發。
1,基於POJO的清理愛你國際和最小侵入性(代碼的嵌套,獨自開發合起來運行)
2,經過依賴注入和麪向接口鬆耦合
三、基於切面(典型的事務管理!!日誌)和慣性進行聲明式編程
四、經過切面和模板減小版式代碼
主要經過,面向Bean、依賴注入以及面向切面三種方式達成
Spring提供了IOC容器,經過配置文件或者註解的方式來管理對象之間的依賴關係
A a = new A()//實例化後用一個變量保存下來(匿名對象) ------------------》Spring用IOC容器 存儲起來~
a.c() //必須初始化才運行 -----------------------> Spring幫忙初始化,實例化(控制器給了spring)
最終實現了 依賴注入:
@autowrite Interfa A a //自動吧他的實現類注入進來
@Resource(「aa」)//IOC容器種類的id爲「aa」的對象自動注入到這裏
@autowrite A a //根據類型自動注入
Spring的注入方式
一、 setter
二、 構造方法
三、強制賦值
面向切面,AOP核心思想--解耦! 把一個總體拆開,分別開發,發佈時候,再組裝到一塊兒運行,切面就是規則!
好比 事務;
開啓事務 執行事務 事務回滾 關閉事務 這就是規則!!!!!!
這種有規律的,就能夠認爲他是固定的,能夠單獨拿出來開發設計,做爲一個模塊(好比日誌啊)。
AOP就是個編程思想而已
關於Spring的使用,特色,網上資料不少,你們能夠本身找找學習下。本博客主要對於源碼進行解讀。
在典型的面型對象開發方式中,可能要將日誌記錄語句放在全部方法和Java類種才能實現日誌功能。而在AOP方式中,能夠反過來將日誌服務模塊化,並以聲明的方式將他們應用到須要日誌的組件上。Java類不須要知道日誌服務的存在,也不想須要考慮相關的代碼。
AOP的功能徹底集成到了Spring事務管理、日誌和其餘各類特性的上下文中
authentication權限認證
Logging日誌
Transctions Manager事務
Lazy Loading懶加載
Contex Process 上下文處理
Error Handler 錯誤跟蹤(異常捕獲機制)
Cache緩存
一、除了AOP之外的設計模式
a、 代理模式
b、工廠模式
c、單例模式
d、委派模式
e、策略模式
f、策略模式
g、原型模式
代理模式原理:
一、拿到被代理對象的引用,而後獲取它的接口
二、JDK代理從新生成一個類,同時實現咱們給的代理對象所實現的接口
三、把代理對象的引用拿到
四、從新動態生成一個class字節碼
五、編譯
動態代理 調用哪一個方法就代理哪一個方法
整個類 生成一個新 的類
你們認真仔細研究好代理模式,代理模式在Spring中 應用很是普遍!!!
JDK代理模式實現:
一、定義接口
二、定義實現接口的類
三、 代理類 ,代理類須要實現 InvocationHandler 接口,而後實現 invoke方法
回顧一下,知足代理模式應用場景的三個必要條件,窮取法
一、兩個角色:執行者、被代理對象
二、注重過程,必需要作,被代理對象沒時間作或者不想作(怕羞羞),不專業
三、執行者必須拿到被代理對象的我的資料(執行者持有被代理對象的引用)
例:定義Persion接口
public interface Person { //尋找真愛、相親 void findLove(); // String getSex(); // // String getName(); }
實現這個接口
//小星星、單身
public class XiaoXingxing implements Person{
// private String sex = "女";
// private String name = "小星星";
@Override
public void findLove() {
// System.out.println("我叫" + this.name + ",性別:" + this.sex + "我找對象的要求是:");
System.out.println("高富帥");
System.out.println("有房有車的");
System.out.println("身高要求180cm以上,體重70kg");
}
// public String getSex() {
// return sex;
// }
//
// public void setSex(String sex) {
// this.sex = sex;
// }
//
// public String getName() {
// return name;
// }
//
// public void setName(String name) {
// this.name = name;
// }
}
代理類
//媒婆 public class Meipo implements InvocationHandler { private Person target; //被代理對象的引用做爲一個成員變量保存下來了 在下面調用時候的 的 ///////////////////////// 下面的嗲用 //獲取被代理人的我的資料爲,爲了能讓他代理任何對象 public Object getInstance(Person target) throws Exception { this.target = target; Class clazz = target.getClass(); //利用反射機制(最終得到接口) System.out.println("被代理對象的class是:" + clazz); return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this); //this這個參數 指的是 代理人 this.h 就是調用了媒婆的 invoke方法 this指的是invoke這個回調方法 } //代理對象 會自動調用下面invoke方法 @Override public Object invoke (Object proxy, Method method, Object[] args) throws Throwable{ System.out.println("我是媒婆:" + "得給你找個異性才行"); System.out.println("開始進行海選..."); System.out.println("------------"); /////////////////////////////////////////////////////////// //調用的時候 (利用反射機制調用) 對象名.方法名 method.invoke(this.target, args); 這個invoke不是方法名字的invoke 是的話 會陷入死循環 System.out.println("------------"); System.out.println("若是合適的話,就準備辦事"); return null; } }
測試:
public class TestFindLove { public static void main(String[] args) { try { // // Person obj = (Person)new Meipo().getInstance(new XiaoXingxing()); // System.out.println(obj.getClass()); // obj.findLove(); //原理: //1.拿到被代理對象的引用,而後獲取它的接口 //2.JDK代理從新生成一個類,同時實現咱們給的代理對象所實現的接口 //3.把被代理對象的引用也拿到了 //4.從新動態生成一個class字節碼 //5.而後編譯 //獲取字節碼內容 // byte[] data = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{Person.class}); //生成字節碼文件 // FileOutputStream os = new FileOutputStream("E:/GP_WORKSPACE/$Proxy0.class"); //將字節碼輸入到磁盤上 // os.write(data); // os.close(); //是什麼? //爲何? //怎麼作? //解釋: 字節碼 反編譯後 能夠查看
Person obj = (Person)new GPMeipo().getInstance(new XiaoXingxing()); //返回一個代理對象 代理出來的這個對象能夠強轉這個接口類 System.out.println(obj.getClass()); //這個Object對象 並非 lcy的引用了 徹底是一個新的對象 obj.findLove(); //動態代理 須要調用哪一個方法 就調用哪一個方法 整個類都是新的類了 新的字節碼 } catch (Exception e) { e.printStackTrace(); } } }
也能夠不用 JDK的任何東西 本身實現動態代理!!
不用jdk的任何東西!
首先規定有個InvocationHandler 有個 invoke方法
import java.lang.reflect.Method; public interface GPInvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }
實現個Proxy 裏面有 InvocationHandler引用 有 newInstance的方法 classloader方法
import java.io.File; import java.io.FileWriter; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import javax.tools.JavaCompiler; import javax.tools.JavaCompiler.CompilationTask; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; //生成代理對象的代碼 public class GPPorxy { private static String ln = "\r\n"; public static Object newProxyInstance(GPClassLoader classLoader,Class<?>[] interfaces,GPInvocationHandler h){ try{ //一、生成源代碼 String proxySrc = generateSrc(interfaces[0]); //二、將生成的源代碼輸出到磁盤,保存爲.java文件 String filePath = GPPorxy.class.getResource("").getPath(); File f = new File(filePath + "$Proxy0.java"); FileWriter fw = new FileWriter(f); fw.write(proxySrc); fw.flush(); fw.close(); //三、編譯源代碼,而且生成.class文件 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null); Iterable iterable = manager.getJavaFileObjects(f); CompilationTask task = compiler.getTask(null, manager, null, null, null, iterable); task.call(); manager.close(); //4.將class文件中的內容,動態加載到JVM中來 //5.返回被代理後的代理對象 Class proxyClass = classLoader.findClass("$Proxy0"); Constructor c = proxyClass.getConstructor(GPInvocationHandler.class); //拿到構造方法 f.delete(); return c.newInstance(h); }catch (Exception e) { e.printStackTrace(); } return null; } private static String generateSrc(Class<?> interfaces){ StringBuffer src = new StringBuffer(); src.append("package com.gupaoedu.vip.custom;" + ln); src.append("import java.lang.reflect.Method;" + ln); src.append("public class $Proxy0 implements " + interfaces.getName() + "{" + ln); src.append("GPInvocationHandler h;" + ln); src.append("public $Proxy0(GPInvocationHandler h) {" + ln); src.append("this.h = h;" + ln); src.append("}" + ln); for (Method m : interfaces.getMethods()) { //那麼多方法 須要拿出來 src.append("public " + m.getReturnType().getName() + " " + m.getName() + "(){" + ln); src.append("try{" + ln); src.append("Method m = " + interfaces.getName() + ".class.getMethod(\"" +m.getName()+"\",new Class[]{});" + ln); //方法名 參數等等 src.append("this.h.invoke(this,m,null);" + ln); src.append("}catch(Throwable e){e.printStackTrace();}" + ln); src.append("}" + ln); } src.append("}"); return src.toString(); } }
classloader類
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; //代碼生成、編譯、從新動態load到JVM public class GPClassLoader extends ClassLoader{ private File baseDir; public GPClassLoader(){ String basePath = GPClassLoader.class.getResource("").getPath(); this.baseDir = new java.io.File(basePath); //保存路徑 } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { String className = GPClassLoader.class.getPackage().getName() + "." + name; //找到這個class文件 if(baseDir != null){ File classFile = new File(baseDir,name.replaceAll("\\.", "/") + ".class"); if(classFile.exists()){ FileInputStream in = null; ByteArrayOutputStream out = null; try{ in = new FileInputStream(classFile); out = new ByteArrayOutputStream(); byte [] buff = new byte[1024]; //緩衝區 int len; while ((len = in.read(buff)) != -1) { out.write(buff, 0, len); } //所有讀完 return defineClass(className, out.toByteArray(), 0,out.size()); //搞到jvm中去 }catch (Exception e) { e.printStackTrace(); }finally{ if(null != in){ try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if(null != out){ try { out.close(); } catch (IOException e) { e.printStackTrace(); } } classFile.delete(); } } } return null; } }
代理類媒婆 必須實現這個類
import java.lang.reflect.Method; import com.gupaoedu.vip.proxy.jdk.Person; public class GPMeipo implements GPInvocationHandler{ private Person target; //獲取被代理人的我的資料 public Object getInstance(Person target) throws Exception{ this.target = target; Class clazz = target.getClass(); System.out.println("被代理對象的class是:"+clazz); return GPPorxy.newProxyInstance(new GPClassLoader(), clazz.getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("我是媒婆:得給你找個異性才行"); System.out.println("開始進行海選..."); System.out.println("------------"); method.invoke(this.target, args); System.out.println("------------"); System.out.println("若是合適的話,就準備辦事"); return null; } }
注意 Java中 $符號的 約定俗成 被代理的類
JDK 必須 實現接口!!!!
知足代理模式應用場景的三個必要條件,
一、須要有兩個角色 執行者 和 被代理對象
二、注重過程,必需要作,被代理對象不作
三、執行者必須拿到被代理對象的資料(執行者持有被代理對象的引用)
代理模式總結到底層就是:字節碼重組! (字節碼重組時候 對象要強制轉換,必需要實現一個接口)
Java源代碼--->編譯---->字節碼(在原始的加了東西)-->加載到jvm中
而後 cglib不須要,Spring主要用的cglib作動態代理 定義一個類 自動生成一個類 自動繼承這個類 子類引用指向父類 看下面:
(一樣作了字節碼重組 事情)
是繼承關係
public class YunZhongYu { public void findLove(){ System.out.println("膚白貌美大長腿"); } }
定義代理類:
import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class GPMeipo implements MethodInterceptor{ // MethodInterceptor這是cglib裏面的 //疑問? //好像並無持有被代理對象的引用 public Object getInstance(Class clazz) throws Exception{ //經過反射機制進行實例化 Enhancer enhancer = new Enhancer(); //用來動態生成class //把父類設置爲誰? //這一步就是告訴cglib,生成的子類須要繼承哪一個類 enhancer.setSuperclass(clazz); //設置回調 enhancer.setCallback(this); //業務邏輯 指的是下面的 intercept 回調方法 //第一步、生成源代碼 //第二步、編譯成class文件 //第三步、加載到JVM中,並返回被代理對象 return enhancer.create(); } //一樣是作了字節碼重組這樣一件事情 //對於使用API的用戶來講,是無感知 @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { //要乾的哪些事情 obj是生成之後的子類的引用 調用子類的引用就會調用這個子 intercept方法 調用super方法 System.out.println("我是GP媒婆:" + "得給你找個異性才行"); System.out.println("開始進行海選..."); System.out.println("------------"); //這個obj的引用是由CGLib給咱們new出來的 //cglib new出來之後的對象,是被代理對象的子類(繼承了咱們本身寫的那個類) //OOP, 在new子類以前,實際上默認先調用了咱們super()方法的, //new了子類的同時,必須先new出來父類,這就至關因而間接的持有了咱們父類的引用 //子類重寫了父類的全部的方法 //咱們改變子類對象的某些屬性,是能夠間接的操做父類的屬性的 proxy.invokeSuper(obj, args); //能夠直接調用 調用的是父類哦 System.out.println("------------"); System.out.println("若是合適的話,就準備辦事"); return null; } }
測試類
public class TestGglibProxy { public static void main(String[] args) { //JDK的動態代理是經過接口來進行強制轉換的 //生成之後的代理對象,能夠強制轉換爲接口 //CGLib的動態代理是經過生成一個被代理對象的子類,而後重寫父類的方法 //生成之後的對象,能夠強制轉換爲被代理對象(也就是用本身寫的類) //子類引用賦值給父類 try { YunZhongYu obj = (YunZhongYu)new GPMeipo().getInstance(YunZhongYu.class); //面向接口 對外開放 制定規範 接口就是規範 通常是是字符串 包名 類名 方法名之類的 obj.findLove(); } catch (Exception e) { e.printStackTrace(); } } }
代理能夠實現 在每個方法調用以前加一些代碼,方法嗲用以後加一些代碼
AOP: 事務代理、 日誌監聽
Service方法 開啓一個事務 事務的執行是由咱們本身的代碼完成的
一、監聽到是否有異常,可能須要根據異常的類型來決定這個事務是否好回滾or繼續提交?(commit or rollback?)
二、事務要關閉掉
經過動態代理給加了代碼
-------------------------------------工廠模式
首先要區分 生產者 消費者 消費者不關心工廠、過程 只關心結果 從工廠取東西哈哈
簡單工廠:
定義接口:
//產品接口 //汽車須要知足必定的標準 public interface Car { //規定汽車的品牌 String getName(); }
實現之:
public class Bmw implements Car{ @Override public String getName() { return "BMW"; } }
public class Benz implements Car{ @Override public String getName() { return "Benz"; } }
public class Audi implements Car{ @Override public String getName() { return "Audi"; } }
定義工廠類
import com.gupaoedu.vip.factory.Audi; import com.gupaoedu.vip.factory.Benz; import com.gupaoedu.vip.factory.Bmw; import com.gupaoedu.vip.factory.Car; //對於這個工廠來講(太強大了) //爲何? //這個工廠啥都能幹(不符合現實) //編碼也是一種藝術(融匯貫通),藝術來源於生活,迴歸到生活的 public class SimpleFactory { //實現統一管理、專業化管理 //若是沒有工廠模式,小做坊,沒有執行標準的 //若是買到三無產品(沒有標準) //衛生監督局工做難度會大大減輕 //中國製造(按人家的標準執行) //中國製造向中國創造改變(技術不是問題了,問題是什麼?思惟能力) //碼農就是執行標準的人 //系統架構師,就是制定標準的人 //不僅作一個技術者,更要作一個思考者 public Car getCar(String name){ if("BMW".equalsIgnoreCase(name)){ //Spring中的工廠模式 //Bean //BeanFactory(生成Bean) //單例的Bean //被代理過的Bean //最原始的Bean(原型) //List類型的Bean //做用域不一樣的Bean //getBean //很是的紊亂,維護困難 //解耦(鬆耦合開發) return new Bmw(); }else if("Benz".equalsIgnoreCase(name)){ return new Benz(); }else if("Audi".equalsIgnoreCase(name)){ return new Audi(); }else{ System.out.println("這個產品產不出來"); return null; } } }
測試類(消費者)
public class SimpleFactoryTest { public static void main(String[] args) { //這邊就是咱們的消費者 Car car = new SimpleFactory().getCar("Audi"); System.out.println(car.getName()); } }
接下來是 工廠方法模式
定義工廠接口
實現不一樣工廠
消費者使用
一、定義工廠接口
import com.gupaoedu.vip.factory.Car; //工廠接口,就定義了全部工廠的執行標準 public interface Factory { //符合汽車上路標準 //尾氣排放標準 //電子設備安全係數 //必須配備安全帶、安全氣囊 //輪胎的耐磨程度 Car getCar(); }
二、實現這個工廠接口
import com.gupaoedu.vip.factory.Bmw; import com.gupaoedu.vip.factory.Car; public class BmwFactory implements Factory { @Override public Car getCar() { return new Bmw(); } }
import com.gupaoedu.vip.factory.Benz; import com.gupaoedu.vip.factory.Car; public class BenzFactory implements Factory { @Override public Car getCar() { return new Benz(); } }
三、測試類
public class FactoryTest { public static void main(String[] args) { //工廠方法模式 //各個產品的生產商,都擁有各自的工廠 //生產工藝,生成的高科技程度都是不同的 Factory factory = new AudiFactory(); System.out.println(factory.getCar()); //須要用戶關心,這個產品的生產商 factory = new BmwFactory(); System.out.println(factory.getCar()); //增長的代碼的使用複雜度 //抽象工廠模式 } }
改進版的工廠方法模式,抽象工廠模式:
這個再也不是 接口了 而是 抽象類
抽象類能夠引用本身的方法!
默認的方法
import com.gupaoedu.vip.factory.Car; public class DefaultFactory extends AbstractFactory { private AudiFactory defaultFactory = new AudiFactory(); public Car getCar() { return defaultFactory.getCar(); } }
工廠方法
import com.gupaoedu.vip.factory.Car; public abstract class AbstractFactory { protected abstract Car getCar(); //這段代碼就是動態配置的功能 //固定模式的委派 public Car getCar(String name){ if("BMW".equalsIgnoreCase(name)){ return new BmwFactory().getCar(); }else if("Benz".equalsIgnoreCase(name)){ return new BenzFactory().getCar(); }else if("Audi".equalsIgnoreCase(name)){ return new AudiFactory().getCar(); }else{ System.out.println("這個產品產不出來"); return null; } } }
import com.gupaoedu.vip.factory.Audi; import com.gupaoedu.vip.factory.Car; //具體的業務邏輯封裝 public class AudiFactory extends AbstractFactory { @Override public Car getCar() { return new Audi(); } }
public class BenzFactory extends AbstractFactory { @Override public Car getCar() { return new Benz(); } }
public class BmwFactory extends AbstractFactory { @Override public Car getCar() { return new Bmw(); } }
單例模式:
整個系統從啓動到終止,自會有一個實例
在應用中遇到功能性衝突的時候,須要用到單例模式
單例模式有7種寫 法!!!
1.
1 public class Singleton implements java.io.Serializable { 2 public static Singleton INSTANCE = new Singleton(); 3 protected Singleton() { } 4 private Object readResolve() { 5 return INSTANCE; 6 } 7 }
二、
//懶漢式單例類.在第一次調用的時候實例化本身 public class Singleton1 { //一、第一步先將構造方法私有化 private Singleton1() {} //二、而後聲明一個靜態變量保存單例的引用 private static Singleton1 single = null; //三、經過提供一個靜態方法來得到單例的引用 //不安全的 public static Singleton1 getInstance() { if (single == null) { single = new Singleton1(); } return single; } }
三、
//懶漢式單例.保證線程安全 public class Singleton2 { //一、第一步先將構造方法私有化 private Singleton2() {} //二、而後聲明一個靜態變量保存單例的引用 private static Singleton2 single=null; //三、經過提供一個靜態方法來得到單例的引用 //爲了保證多線程環境下正確訪問,給方法加上同步鎖synchronized //慎用 synchronized 關鍵字,阻塞,性能很是低下的 //加上synchronized關鍵字之後,對於getInstance()方法來講,它始終單線程來訪問 //沒有充分利用上咱們的計算機資源,形成資源的浪費 public static synchronized Singleton2 getInstance() { if (single == null) { single = new Singleton2(); } return single; } }
四、
//懶漢式單例.雙重鎖檢查 public class Singleton3 { //一、第一步先將構造方法私有化 private Singleton3() {} //二、而後聲明一個靜態變量保存單例的引用 private static Singleton3 single=null; //三、經過提供一個靜態方法來得到單例的引用 //爲了保證多線程環境下的另外一種實現方式,雙重鎖檢查 //性能,第一次的時候 public static Singleton3 getInstance() { if (single == null) { synchronized (Singleton3.class) { if (single == null) { single = new Singleton3(); } } } return single; } }
五、
//懶漢式(靜態內部類) //這種寫法,即解決安全問題,又解決了性能問題 //這個代碼,沒有浪費一個字 public class Singleton4 { //一、先聲明一個靜態內部類 //private 私有的保證別人不能修改 //static 保證全局惟一 private static class LazyHolder { //final 爲了防止內部誤操做,代理模式,GgLib的代理模式 private static final Singleton4 INSTANCE = new Singleton4(); } //二、將默認構造方法私有化 private Singleton4 (){} //至關於有一個默認的public的無參的構造方法,就意味着在代碼中隨時均可以new出來 //三、一樣提供靜態方法獲取實例 //final 確保別人不能覆蓋 public static final Singleton4 getInstance() { //方法中的邏輯,是要在用戶調用的時候纔開始執行的 //方法中實現邏輯須要分配內存,也是調用時才分配的 return LazyHolder.INSTANCE; } // static int a = 1; // //無論該class有沒有實例化,static靜態塊總會在classLoader執行完之後,就加載完畢 // static{ // //靜態塊中的內容,只能訪問靜態屬性和靜態方法 // //只要是靜態方法或者屬性,直接能夠用Class的名字就能點出來 // Singleton4.a = 2; // //JVM 內存中的靜態區,這一塊的內容是公共的 // } } //咱們所寫的全部的代碼,在java的反射機制面前,都是裸奔的 //反射機制是能夠拿到private修飾的內容的 //咱們能夠理解成即便加上private也不靠譜(按正常套路出牌,貌似能夠) //類裝載到JVM中過程 //一、從上往下(必須聲明在前,使用在後) //先屬性、後方法 //先靜態、後動態
六、
//相似Spring裏面的方法,將類名註冊,下次從裏面直接獲取。 public class Singleton6 { private static Map<String,Singleton6> map = new HashMap<String,Singleton6>(); static { Singleton6 single = new Singleton6(); map.put(single.getClass().getName(), single); } //保護的默認構造子 protected Singleton6(){} //靜態工廠方法,返還此類唯一的實例 public static Singleton6 getInstance(String name) { if(name == null) { name = Singleton6.class.getName(); } if(map.get(name) == null) { try { map.put(name, (Singleton6) Class.forName(name).newInstance()); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } return map.get(name); } }
測試類
public class TestMain { public static void main(String[] args){ TestSingleton ts1 = TestSingleton.getInstance(); ts1.setName("james"); TestSingleton ts2 = TestSingleton.getInstance(); ts2.setName("tom"); ts1.printInfo(); ts2.printInfo(); if(ts1 == ts2){ System.out.println("建立的是同一個實例" + ts1.getName()); }else{ System.out.println("建立的不是同一個實例" + ts1.getName()); } } }
public class TestSingleton { String name = null; private TestSingleton() {} //注意這裏用到了volatile關鍵字 private static volatile TestSingleton instance = null; public static TestSingleton getInstance() { if (instance == null) { synchronized (TestSingleton.class) { if (instance == null) { instance = new TestSingleton(); } } } return instance; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void printInfo() { System.out.println("the name is " + name); } }
public class TestThread { public static void main(String[] args) { //啓動100線程同時去搶CPU int count = 100; //發令槍,測試併發常常用到 CountDownLatch latch = new CountDownLatch(count); //Set默認去去重的,set是自己線程不安全的 // final Set<Singleton1> syncSet = Collections.synchronizedSet(new HashSet<Singleton1>()); for (int i = 0; i < count; i++) { new Thread(){ @Override public void run() { syncSet.add(Singleton1.getInstance()); } }.start(); latch.countDown(); } try { latch.await();//等待全部線程所有完成,最終輸出結果 System.out.println(syncSet.size()); } catch (InterruptedException e) { e.printStackTrace(); } } }
委派模式:
1相似中介的功能(委託機制)
2只有被委託人的引用
兩個角色 受託人 委託人
定義一個接口
public class Dispatcher implements IExector{ IExector exector; Dispatcher(IExector exector){ this.exector = exector; } //項目經理,雖然也有執行方法 //可是他的工做職責是不同的 public void doing() { this.exector.doing(); } }
兩個員工類實現這個接口
public class ExectorA implements IExector { @Override public void doing() { System.out.println("xxoo"); } }
public class ExectorB implements IExector{ @Override public void doing() { System.out.println("員工B開始執行任務"); } }
項目經理類
public class Dispatcher implements IExector{ IExector exector; Dispatcher(IExector exector){ this.exector = exector; } //項目經理,雖然也有執行方法 //可是他的工做職責是不同的 public void doing() { this.exector.doing(); } }
測試
public class DispatcherTest { public static void main(String[] args) { Dispatcher dispatcher = new Dispatcher(new ExectorA()); //看上去好像是咱們的項目經理在幹活 //但實際幹活的人是普通員工 //這就是典型,幹活是個人,功勞是你的 dispatcher.doing(); } }
IOC容器中,有一個Register的東西(爲了告訴咱們的容器,在這個類被初始化的過程當中,須要作不少不一樣的邏輯處理,須要實現多個任務執行者,分別實現各自的功能 )
關於策略模式,參考系 Comparator方法就能夠啦 返回 -1 0 1這種的
a、比較器接口
b、調用時候有本身的實現
//比較器 public interface Comparator { int compareTo(Object obj1,Object obj2); }
public class ObjectComparator implements Comparator{ @Override public int compareTo(Object obj1, Object obj2) { return 0; } }
public class NumberComparator implements Comparator{ @Override public int compareTo(Object obj1, Object obj2) { return 0; } }
public class MyList { public void sort(Comparator com){ // com.compareTo(obj1, obj2); System.out.println("執行邏輯"); } }
public class MyListTest { public static void main(String[] args) { //new MyList().sort(new NumberComparator()); //策略模式 // List<Long> numbers = new ArrayList<Long>(); // // Collections.sort(numbers, new Comparator<Long>() { // // @Override // //返回值是固定的 // //0 、-1 、1 // //0 、 >0 、<0 // public int compare(Long o1, Long o2) { // // //中間邏輯是不同的 // // return 0; // } // // // }); } }
原型模式:
首先要設計個原型
實現 Cloneable接口
public class ConcretePrototype implements Cloneable{ private int age; private String name; public ArrayList<String> list = new ArrayList<String>(); protected Object clone() throws CloneNotSupportedException { ConcretePrototype prototype = null; try{ prototype = (ConcretePrototype)super.clone(); prototype.list = (ArrayList)list.clone(); //克隆基於字節碼的 //用反射,或者循環 }catch(Exception e){ } return prototype; } //定義上100個屬性 public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
public class CloneTest { public static void main(String[] args) { ConcretePrototype cp = new ConcretePrototype(); cp.setAge(18); cp.setName("Tom"); //cp.list.add("Tom"); try { ConcretePrototype copy = (ConcretePrototype)cp.clone(); System.out.println(copy.list == cp.list); System.out.println(copy.getAge() + "," + copy.getName() + copy.list.size()); } catch (CloneNotSupportedException e) { e.printStackTrace(); } //就是一個現成的對象,這個對象裏面有已經設置好的值 //當我要新建一個對象,而且要給新建的對象賦值,並且賦值內容要跟以前的如出一轍 //ConcretePrototype cp = new ConcretePrototype(); //cp.setAge(18); //ConcretePrototype copy = new ConcretePrototype(); //copy.setAge(cp.getAge()); //copy.setName(cp.getName()); //用循環,用反射,確實能夠的(反射性能並不高) //字節碼複製newInstance() //ConcretePrototype copy = cp; //ORM的時候常常用到的 //可以直接拷貝其實際內容的數據類型/只支持9種,八大基本數據類型+String 淺拷貝 //深拷貝 } }
原型模式:
//猴子 public class Monkey { //身高 protected int height;//基本 //體重 protected int weight; //生日 protected Date birthday;//不是基本類型 public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }
public class TestPrototype { public static void main(String[] args) { TheGreatestSage sage = new TheGreatestSage(); sage.change(); //跟《西遊記》中描述的一致,怎麼辦? } }
public class GoldRingedStaff implements Serializable{ private float height = 100; //長度 private float diameter = 10;//直徑 /** * 金箍棒長大 */ public void grow(){ this.diameter *= 2; this.height *= 2; } /** * 金箍棒縮小 */ public void shrink(){ this.diameter /= 2; this.height /= 2; } }
/** * 齊天大聖 * */ public class TheGreatestSage extends Monkey implements Cloneable,Serializable{ //金箍棒 private GoldRingedStaff staff; //從石頭縫裏蹦出來 public TheGreatestSage(){ this.staff = new GoldRingedStaff(); this.birthday = new Date(); this.height = 150; this.weight = 30; System.out.println("------------------------"); } //分身技能 public Object clone(){ //深度克隆 ByteArrayOutputStream bos = null; ObjectOutputStream oos = null; ByteArrayInputStream bis = null; ObjectInputStream ois = null; try { //return super.clone();//默認淺克隆,只克隆八大基本數據類型和String //序列化 bos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(bos); oos.writeObject(this); //反序列化 bis = new ByteArrayInputStream(bos.toByteArray()); ois = new ObjectInputStream(bis); TheGreatestSage copy = (TheGreatestSage)ois.readObject(); copy.birthday = new Date(); return copy; } catch (Exception e) { e.printStackTrace(); return null; }finally{ try { bos.close(); oos.close(); bis.close(); ois.close(); } catch (IOException e) { e.printStackTrace(); } } } //變化 public void change(){ TheGreatestSage copySage = (TheGreatestSage)clone(); System.out.println("大聖本尊生日是:" + this.getBirthday().getTime()); System.out.println("克隆大聖的生日是:" + copySage.getBirthday().getTime()); System.out.println("大聖本尊和克隆大聖是否爲同一個對象:" + (this == copySage)); System.out.println("大聖本尊持有的金箍棒跟克隆大聖持有金箍棒是否爲同一個對象:" + (this.getStaff() == copySage.getStaff())); } public GoldRingedStaff getStaff() { return staff; } public void setStaff(GoldRingedStaff staff) { this.staff = staff; } }
模板模式:
模板(固定的執行流程)
定義衝飲料的機器:
//衝飲料(拿出去賣錢了) public abstract class Bevegrage { //不能被重寫 public final void create(){ //一、把水燒開 boilWater(); //二、把杯子準備好、原材料放到杯中 pourInCup(); //三、用水沖泡 brew(); //四、添加輔料 addCoundiments(); } public abstract void pourInCup(); public abstract void addCoundiments(); public void brew(){ System.out.println("將開水放入杯中進行沖泡"); }; public void boilWater(){ System.out.println("燒開水,燒到100度能夠起鍋了"); } }
實現爲衝咖啡的
public class Coffee extends Bevegrage{ //原材料放到杯中 public void pourInCup() { System.out.println("將咖啡倒入杯中"); } //房輔料 public void addCoundiments() { System.out.println("添加牛奶和糖"); } }
實現爲泡茶的
public class Tea extends Bevegrage{ //原材料放到杯中 public void pourInCup() { System.out.println("將茶葉放入杯中"); } //房輔料 public void addCoundiments() { System.out.println("添加蜂蜜"); } }
測試類
public class TestTemplate { public static void main(String[] args) { // Coffee coffee = new Coffee(); // coffee.create(); Tea tea = new Tea(); tea.create(); } //SpringJDBC //是java規範,各個數據庫廠商本身去實現 //一、加載驅動類DriverManager //二、創建鏈接 //三、建立語句集(標準語句集、預處理語句集)(語句集? MySQL、Oracle、SQLServer、Access) //四、執行語句集 //五、結果集ResultSet 遊標 //ORM(?) }
Spring JDBC就是個模板模式
是 Java的規範 各個數據庫廠商去實現
一、加載驅動類 DriverManager
二、創建鏈接
三、建立語句集(標準語句集、預處理語句集)(語句集合? Mysql oracle sqlserver access 語句不太同樣哦)
四、執行語句集
五、結果集ResultSet 遊標
ORM (鏈接的是哪一個對象 映射哪一個結果 List or 自定義的類 仍是??運行時候才知道)