在Java Spring框架中使用的設計模式有哪些
1 簡單工廠模式
當A對象需要調用B對象的方法時,我們需要在A中new一個B的實例,我們把這種方式叫作硬編碼耦合,缺點是一旦需求發生變化,比如需要使用C類來代替B時,就要改寫A類的方法。
假如應用中有上千個類以硬編碼的方式耦合瞭B,改就很頭疼。
於是有瞭簡單工廠模式,又叫靜態工廠方法,就是由一個工廠類根據傳入參數,動態決定應該創建哪個產品類。
Spring中的BeanFactory就是簡單工廠模式的體現,BeanFactory是Spring IOC容器中的一個核心接口,它的定義如下:
可以通過它的具體實現類(如ClassPathXmlApplicationContext)獲取Bean:
BeanFactory bf = new ClassPathXmlApplicationContext("spring.xml"); User userBean = (User) bf.getBean("userBean");
使用者無需自己new,而是通過工廠類的方法getBean獲取對象實例,這就是簡單工廠模式,隻不過Spring是用反射創建Bean。
2 工廠方法模式
簡單工廠中,由工廠類進行所有的邏輯判斷、實例創建。
如果不想在工廠類中進行判斷,可為不同產品提供不同工廠,不同工廠生產不同產品,每個工廠都隻對應一個相應對象,這就是工廠方法模式。
Spring FactoryBean,工廠Bean
定義一個類UserFactoryBean實現FactoryBean接口,主要是在getObject方法裡new一個User對象。
這樣通過getBean(id) 獲得的是該工廠所產生的User實例,而非UserFactoryBean本身實例:
BeanFactory bf = new ClassPathXmlApplicationContext("user.xml"); User userBean = (User) bf.getBean("userFactoryBean");
3 單例模式
一個類在整個系統運行過程中,隻允許產生一個實例。
Spring Bean默認是單例模式。Spring 通過單例註冊表(HashMap)方式:
public class DefaultSingletonBeanRegistry { // 使用 ConcurrentHashMap 保存各種單實例對象 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>; protected Object getSingleton(String beanName) { // 先到 Map 中拿Object Object singletonObject = singletonObjects.get(beanName); // 若沒拿到通過反射創建一個對象實例,並添加到HashMap中 if (singletonObject == null) { singletonObjects.put(beanName, Class.forName(beanName).newInstance()); } // 返回對象實例 return singletonObjects.get(beanName); } }
4 代理模式
它與被代理對象實現相同接口,客戶端必須通過代理才能與被代理的目標類進行交互,而代理一般在交互的過程中(交互前後),進行某些特定處理,比如在調用這個方法前做前置處理,調用這個方法後做後置處理。
好處
可以在目標對象業務功能的基礎上添加一些公共的邏輯,比如我們想給目標對象加入日志、權限管理和事務控制等功能,我們就可以使用代理類來完成,而沒必要修改目標類,從而使得目標類保持穩定。
符合開閉原則,不要隨意修改別人寫好的代碼或方法。
代理又分為
靜態代理
需要定義接口,被代理對象(目標對象)與代理對象(Proxy)一起實現相同接口:
// 抽象接口 public interface IStudentDao { void save(); } // 目標對象 public class StudentDao implements IStudentDao { public void save() { System.out.println("保存成功"); } } // 代理對象 public class StudentDaoProxy implements IStudentDao{ //持有目標對象的引用 private IStudentDao target; public StudentDaoProxy(IStudentDao target){ this.target = target; } //在目標功能對象方法的前後加入事務控制 public void save() { System.out.println("開始事務"); target.save();//執行目標對象的方法 System.out.println("提交事務"); } } public static void main(String[] args) { //創建目標對象 StudentDao target = new StudentDao(); //創建代理對象,把目標對象傳給代理對象,建立代理關系 StudentDaoProxy proxy = new StudentDaoProxy(target); //執行的是代理的方法 proxy.save(); }
動態代理
Spring AOP采用動態代理,即代理類在程序運行時由JVM動態創建。
靜態代理的例子中,代理類(StudentDaoProxy)是自定義的,在程序運行之前就已經編譯完成。
而動態代理,代理類並不是在Java代碼中定義,而是在運行時根據我們在Java代碼中的“指示”動態生成的。
怎麼“指示”JDK去動態地生成代理類呢?
在Java的java.lang.reflect包裡提供瞭一個Proxy類和一個InvocationHandler接口,通過這個類和這個接口可以生成動態代理對象:
1.定義一個InvocationHandler類,將需要擴展的邏輯集中放到這個類中。
比如下面的例子模擬瞭添加事務控制:
public class MyInvocationHandler implements InvocationHandler { private Object obj; public MyInvocationHandler(Object obj){ this.obj=obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("開始事務"); Object result = method.invoke(obj, args); System.out.println("開始事務"); return result; } }
2.使用 Proxy#newProxyInstance 動態創建代理對象
public static void main(String[] args) { //創建目標對象StudentDao IStudentDao stuDAO = new StudentDao(); //創建MyInvocationHandler對象 InvocationHandler handler = new MyInvocationHandler(stuDAO); //使用Proxy.newProxyInstance動態的創建代理對象stuProxy IStudentDao stuProxy = (IStudentDao) Proxy.newProxyInstance(stuDAO.getClass().getClassLoader(), stuDAO.getClass().getInterfaces(), handler); //動用代理對象的方法 stuProxy.save(); }
動態代理的優勢在於可以很方便地對代理類的函數進行統一的處理,而不用修改每個代理類中的方法。
Spring實現瞭通過動態代理對類進行方法級別的切面增強,即動態生成目標對象的代理類,並在代理類的方法中設置攔截器,通過執行攔截器中的邏輯增強瞭代理方法的功能,從而實現AOP。
到此這篇關於在Java Spring框架中使用的設計模式有哪些的文章就介紹到這瞭,更多相關Java Spring 設計模式內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!