日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring框架中的设计模式(三)

發(fā)布時間:2025/3/21 javascript 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring框架中的设计模式(三) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原型模式

這篇文章的第一個設計模式是原型。可以通過官方文檔查找有關Spring作用域中的bean作用域的文章中介紹了類似的概念(prototype)。原型設計模式與有用相同名稱的(prototype)作用域有點相似。此設計模式允許通過復制已存在的對象來創(chuàng)建一個對象的實例。副本應該是真正的副本。這意味著新對象的所有屬性應與復制對象的屬性相同。如果不清楚,比一個簡單的JUnit案例更好的說明:

public class PrototypeTest {

@Test

public void test() {

Robot firstRobot = new Robot("Droid#1");

Robot secondRobot = (Robot) firstRobot.clone();

assertTrue("Cloned robot's instance can't be the same as the"

+" source robot instance",

firstRobot != secondRobot);

assertTrue("Cloned robot's name should be '"+firstRobot.getName()+"'"

+" but was '"+secondRobot.getName()+"'",

secondRobot.getName().equals(firstRobot.getName()));

}

}

class Robot implements Cloneable {

private String name;

public Robot(String name) {

this.name = name;

}

public String getName() {

return this.name;

}

protected Object clone() throws CloneNotSupportedException {

return super.clone();

}

}

在Spring中,在org.springframework.beans.factory.support.AbstractBeanFactory中使用一種特定的原型設計模式,它將初始化bean原型作用域。新對象基于配置文件中的bean定義。我們可以看到,在給定的例子中:

<bean id="shoppingCart" class="com.waitingforcode.data.ShoppingCart" scope="prototype">

<property name="id" value="9"></property>

</bean>

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations={"applicationContext-test.xml"})

public class SpringPrototypeTest {

@Autowired

private BeanFactory beanFactory;

@Test

public void test() {

ShoppingCart cart1 = (ShoppingCart) beanFactory.getBean("shoppingCart");

assertTrue("Id of cart1 should be 9 but was "+cart1.getId(),

cart1.getId() == 9);

cart1.setId(100);

ShoppingCart cart2 = (ShoppingCart) beanFactory.getBean("shoppingCart");

assertTrue("Id of cart2 should be 9 but was "+cart2.getId(),

cart2.getId() == 9);

assertTrue("Id of second cart ("+cart2.getId()+") shouldn't be the same as the first one: "+cart1.getId(),

cart1.getId() != cart2.getId());

cart2.setId(cart1.getId());

assertTrue("Now (after cart2.setId(cart1.getId())), the id of second cart ("+cart2.getId()+") should be the same as the first one: "

+cart1.getId(), cart1.getId() == cart2.getId());

assertTrue("Both instance shouldn't be the same", cart1 != cart2);

}

}

從前面的例子可以看出,ShoppingCart實例是直接從bean定義創(chuàng)建的。最初,cart1和cart2對象的id值為9.它在測試結束時被修改,以證明兩個引用都屬于兩個不同的對象。

對象池

Spring中使用的另一個模型是對象池設計模式。其主要目的在于在一個池中保存特定數量的對象,并根據需要重新使用。通過它,我們可以改善我們想要使用巨型對象的響應時間。巨型意味著這些對象的構造需要很多時間(例如:持有數據庫連接的對象),最好重用已經存在的和未獲取的對象,而不是創(chuàng)建新對象。

Spring還使用線程池來管理其調度部分。一些示例位于org.springframework.scheduling.concurrent中。我們檢索數據庫(Spring JDBC)項目中的對象池的想法。數據庫連接池不是由Spring直接實現(xiàn)的,而是適用于Spring工作方式的項目,如C3P0或Jakarta Commons DBCP連接池。

觀察者

這里呈現(xiàn)的最后一個設計模式是觀察者。當一個或幾個課程正在等待具體事件時可以使用它。觀察者模式由一個科目和觀察員名單組成。一個很好的例子就是GUI界面,其中點擊按鈕(按鈕是主題)會引起聽眾(觀察者)啟動的一些操作(再說的直白點就是電影院一場電影這個subject,需要觀眾(也就是觀察者咯),電影產生的一些畫面產生的事件,比如恐怖 電影給男人女人帶來的不同的感官的感受,傳播到觀察者也就是觀眾的眼里所帶來的不一樣的反應,這個中間一般會添加一個事件傳播者,在后面解釋Spring的例子的時候會說到),例如:打開一個新頁面這個動作。可以參考下面的例子:

public class ObserverTest {

@Test

public void test() {

Observer pageOpener = new PageOpener();

Observer register = new Register();

Button btn = new Button();

btn.addListener(pageOpener);

btn.addListener(register);

btn.clickOn();

assertTrue("Button should be clicked but it wasn't",

btn.wasClicked());

assertTrue("Page opener should be informed about click but it wasn't",

pageOpener.wasInformed());

assertTrue("Register should be informed about click but it wasn't",

register.wasInformed());

}

}

class Button {

private boolean clicked;

private List<observer> listeners;

public List<observer> getListeners() {

if (this.listeners == null) {

this.listeners = new ArrayList<observer>();

}

return this.listeners;

}

public void addListener(Observer observer) {

getListeners().add(observer);

}

public boolean wasClicked() {

return this.clicked;

}

public void clickOn() {

this.clicked = true;

informAll();

}

private void informAll() {

for (Observer observer : getListeners()) {

observer.informAboutEvent();

}

}

}

abstract class Observer {

protected boolean informed;

public void informAboutEvent() {

this.informed = true;

}

public boolean wasInformed() {

return this.informed;

}

}

class PageOpener extends Observer {

@Override

public void informAboutEvent() {

System.out.println("Preparing download of new page");

super.informAboutEvent();

}

}

class Register extends Observer {

@Override

public void informAboutEvent() {

System.out.println("Adding the action to register");

super.informAboutEvent();

}

}

可以看到,關于我們的Button實例點擊的事件被發(fā)送到所有的觀察者對象。從這些對象開始下載頁面內容,第二個將在事件的信息保存在注冊表中。在Spring中,觀察者設計模式用于將與應用程序上下文相關的事件傳輸到org.springframework.context.ApplicationListener的實現(xiàn)。要了解它們的實現(xiàn)方法,我們來看一下AbstractApplicationContext類(老版本的代碼,新版本的請自行對照):

public abstract class AbstractApplicationContext extends DefaultResourceLoader

implements ConfigurableApplicationContext, DisposableBean {

/** Statically specified listeners */

private Set<applicationlistener<?>> applicationListeners = new LinkedHashSet<applicationlistener<?>>();

// some other fields and methods

@Override

public void addApplicationListener(ApplicationListener<?> listener) {

if (this.applicationEventMulticaster != null) {

this.applicationEventMulticaster.addApplicationListener(listener);

}

else {//新版本這里直接咔嚓掉,上面的applicationEventMulticaster一旦為空,就會報錯的

this.applicationListeners.add(listener);

}

}

/**

* Return the list of statically specified ApplicationListeners.

*/

public Collection<applicationlistener<?>> getApplicationListeners() {

return this.applicationListeners;

}

/**

* Add beans that implement ApplicationListener as listeners.

* Doesn't affect other listeners, which can be added without being beans.

*/

protected void registerListeners() {

// Register statically specified listeners first.

for (ApplicationListener<?> listener : getApplicationListeners()) {

getApplicationEventMulticaster().addApplicationListener(listener);

}

// Do not initialize FactoryBeans here: We need to leave all regular beans

// uninitialized to let post-processors apply to them!

String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);

for (String lisName : listenerBeanNames) {

getApplicationEventMulticaster().addApplicationListenerBean(lisName);

}

}

}

在提供的代碼中,監(jiān)聽器在內部添加到應用程序上下文類中,并且在registerListeners()方法之后,它們被注冊到由接口org.springframework.context.event.ApplicationEventMulticaster表示的適當的事件多路廣播器(因為有很多l(xiāng)isteners)。EventMulticaster負責管理不同的listener和向他們發(fā)布事件。

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

private Executor taskExecutor;

private ErrorHandler errorHandler;

public SimpleApplicationEventMulticaster() {

}

public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {

this.setBeanFactory(beanFactory);

}

public void setTaskExecutor(Executor taskExecutor) {

this.taskExecutor = taskExecutor;

}

protected Executor getTaskExecutor() {

return this.taskExecutor;

}

public void setErrorHandler(ErrorHandler errorHandler) {

this.errorHandler = errorHandler;

}

protected ErrorHandler getErrorHandler() {

return this.errorHandler;

}

public void multicastEvent(ApplicationEvent event) {

this.multicastEvent(event, this.resolveDefaultEventType(event));

}

//發(fā)布事件:通過池執(zhí)行任務的方式來做并發(fā)處理,這樣就把之前的對象池模式給利用上了

public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {

ResolvableType type = eventType != null?eventType:this.resolveDefaultEventType(event);

Iterator var4 = this.getApplicationListeners(event, type).iterator();

while(var4.hasNext()) {

final ApplicationListener<?> listener = (ApplicationListener)var4.next();

Executor executor = this.getTaskExecutor();

if(executor != null) {

executor.execute(new Runnable() {

public void run() {

SimpleApplicationEventMulticaster.this.invokeListener(listener, event);

}

});

} else {

this.invokeListener(listener, event);

}

}

}

...

}

這次我們講3種設計模式:用于在同一個調用作用域內創(chuàng)建bean的原型,避免重新創(chuàng)建巨型對象的對象池,以及將應用程序的上下文事件分派給適當的監(jiān)聽器的觀察者。

《新程序員》:云原生和全面數字化實踐50位技術專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的Spring框架中的设计模式(三)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。