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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

spring框架搭建第一天

發布時間:2024/9/30 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring框架搭建第一天 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

      • 1. 從jdbc的標準代碼了解程序的耦合性
        • 簡單理解耦合:程序之間的依賴關系
      • 2. 基本的三層
        • dao層
        • service層
        • 模擬的controller層(servlet)
        • 存在的問題
      • 3. 使用工廠模式解決代碼耦合性問題
        • 什么是簡單工廠模式
        • 簡單工廠模式如何解耦(后續有待深究)
        • 使用工廠模式解決代碼耦合
      • 4. 使用單例模式調對象復用性
        • 讓工廠不僅負責實例化對象還管理對象
          • 修改BeanFactory
        • 什么是單例模式
      • 5. 開始Spring框架
        • 5.1 控制反轉IOC
        • 5.2 創建一個spring工程
        • 5.3 Spring是如何加載配置文件(Spring是什么時候實例化對象的)
      • 6. Spring對bean的管理
        • 6.1 創建bean的三種方式
          • 6.1.1 使用默認構造函數創建bean
          • 6.1.2 使用普通工廠中的方法創建對象
          • 6.1.3 使用工廠中的靜態方法創建對象
        • 6.2 bean的作用范圍
        • 6.3 bean的生命周期

1. 從jdbc的標準代碼了解程序的耦合性

import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.PreparedStatement;public class JdbcDemo1 {public static void main(String[] args) throws Exception{//Class.forName("com.mysql.jdbc.Driver");DriverManager.registerDriver(new com.mysql.jdbc.Driver());Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?characterEncoding=utf-8", "root", "123456");PreparedStatement ps = conn.prepareStatement("insert into account(name, money) values(?,?)");ps.setString(1,"bbb");ps.setFloat(2,2000);ps.executeUpdate();ps.close();conn.close();} }

程序執行過程,

  • 注冊驅動
  • 獲取鏈接
  • 獲取操作數據庫的預處理對象
  • 執行sql語句,得到結果集(本例是新增操作,故沒有結果集)
  • 遍歷結果集
  • 依次關閉結果集,預處理對象,連接。
    當我們把相關jar包去掉

    可以發現,沒有myql的驅動,將無法編譯。此時可以理解為程序的耦合。

簡單理解耦合:程序之間的依賴關系

耦合包括:

  • 類之間的依賴關系
  • 方法之間的依賴關系

如何解耦
降低程序之間的依賴

  • 編譯期間不依賴,運行時才依賴(典型例子:DriverManager.registerDriver()轉化為用反射來加載驅動Class.forName)

解耦的思路:

  • 使用反射來創建對象,避免使用new關鍵字。
  • 通過讀取配置文件來獲取要創建的對象全限定類名。
  • 2. 基本的三層

    dao層

    package com.ssm.dao.impl;import com.ssm.dao.IAccountDao;public class AccountDao implements IAccountDao {public void saveAccount() {System.out.println("賬戶已保存!");} } package com.ssm.dao; /*** 賬戶的持久層接口*/ public interface IAccountDao {//模擬保存賬戶void saveAccount(); }

    service層

    package com.ssm.service.impl;import com.ssm.dao.IAccountDao; import com.ssm.dao.impl.AccountDao; import com.ssm.factory.BeanFactory; import com.ssm.service.IAccountService;import java.util.PriorityQueue;public class AccountServiceImpl implements IAccountService {private IAccountDao accountDao = new AccountDao();public void saveAccount(){accountDao.saveAccount();} } package com.ssm.service;/*** 賬戶業務層*/ public interface IAccountService {//保存賬戶void saveAccount(); }

    模擬的controller層(servlet)

    package com.ssm.ul;import com.ssm.factory.BeanFactory; import com.ssm.service.IAccountService; import com.ssm.service.impl.AccountServiceImpl; /**模擬表現層*/ public class Client {public static void main(String[] args){IAccountService as = new AccountServiceImpl();as.saveAccount();} }

    存在的問題

  • controller層調用service層使用了new關鍵字,如果AccountServiceImpl.java不存在,則會編譯不通過。代碼耦合性太強。
  • 假如有多次調用controller(main()多次執行),每次執行都會new一個AccountServiceImpl,AccountDao。假如執行5次controller,就會有10個service和dao對象在內存中。在高并發下性能不好
  • 3. 使用工廠模式解決代碼耦合性問題

    什么是簡單工廠模式

    簡單工廠模式又稱為靜態工廠模式,它屬于創建型模式,但非23種設計模式之一。它可以根據傳入的參數來返回不同類的實例。簡單工廠模式專門定義一個類來負責創建其他類的實例,被創建的實例通常都具有共同的父類。

    角色作用
    工廠角色(Creator)是簡單工廠模式的核心,它負責實現創建所有具體產品類的實例。工廠類可以被外界直接調用,創建所需的產品對象。
    抽象產品角色(Product)是所有具體產品角色的父類,它負責描述所有實例所共有的公共接口。
    具體產品角色(Concrete Product)繼承自抽象產品角色,一般為多個,是簡單工廠模式的創建目標。工廠類返回的都是該角色的某一具體產品。

    簡單工廠模式如何解耦(后續有待深究)

    直接new一個對象是最簡單的創建對象的方式。但是它也加強了兩個對象A和B之間的耦合性。使用簡單工廠模式,在A想使用B對象的時候,可以向工廠角色(Creator)請求創建一個實例對象,這樣就避免了直接實例化B對象。降低了耦合性。

    使用工廠模式解決代碼耦合

    package com.ssm.factory;import java.io.IOException; import java.io.InputStream; import java.util.Properties;/*** 創建一個bean對象的工廠*/ public class BeanFactory {private static Properties props;static {try {props = new Properties();//getResourceAsStream(String path):默認則是從ClassPath根下獲取,path不能以’/'開頭,最終是由ClassLoader獲取資源。InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");System.out.println(in);props.load(in);} catch (IOException e) {e.printStackTrace();throw new ExceptionInInitializerError("初始化properties失敗!");}}/*** 根據Bean名稱獲取Bean對象* @param beanName* @return*/public static Object getBean(String beanName){Object bean = null;try {String beanPath = props.getProperty(beanName);System.out.println("beanPath:"+beanPath);bean = Class.forName(beanPath).newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return bean;} }

    工廠讀取的配置文件

    accountService=com.ssm.service.impl.AccountServiceImpl accuountDao=com.ssm.dao.impl.AccountDao

    修改各處的對象實例化方式
    比如controller

    //IAccountService as = new AccountServiceImpl();IAccountService as = (IAccountService) BeanFactory.getBean("accountService");

    4. 使用單例模式調對象復用性

    前面已經使用簡單工廠模式降低了Client對AccountServiceImpl的耦合性,但是代碼仍然存在一個問題,那就是每次調用main()都會讓BeanFactory.getBean()實例化一個對象,多次調用就會有多個實例對象產生,從而影響代碼性能。那么如何讓程序在運行中只讓一個類只實例化一個對象呢?

    讓工廠不僅負責實例化對象還管理對象

    前面實例化對象的工作是交給BeanFactory的,每次有實例化對象的請求過來,它就是實例化一個請求。那么能不能讓BeanFactory先實例化所有對象,把它們管理起來。每次有實例化請求過來,就返回需要實例化對象的引用。這樣就能保證內存中IAccountService只有一個實例化對象。

    修改BeanFactory

    修改靜態代碼塊

    static {try {props = new Properties();//getResourceAsStream(String path):默認則是從ClassPath根下獲取,path不能以’/'開頭,最終是由ClassLoader獲取資源。InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");props.load(in);beans = new HashMap<String, Object>();Enumeration keys = props.keys();while (keys.hasMoreElements()){String key = keys.nextElement().toString();String keyPath = props.getProperty(key);Object bean = Class.forName(keyPath).newInstance();beans.put(key,bean);}} catch (Exception e) {e.printStackTrace();throw new ExceptionInInitializerError("初始化properties失敗!");}}

    此時,BeanFactory中已經有所需要的對象實例了,那么獲取bean的方法也要改

    public static Object getBean(String beanName){return beans.get(beanName);}

    什么是單例模式

    單例模式(Singleton Pattern)是 Java 中最簡單的設計模式之一。與前面說的簡單工廠模式一樣,這種類型的設計模式也屬于創建型模式,它提供了一種創建對象的最佳方式。

    這種模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被創建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。

    5. 開始Spring框架

    抽象前面的模型
    更改前的

    更改后的

    5.1 控制反轉IOC

    百度詞條解釋

    作用:降低程序代碼的耦合(解除代碼間的依賴關系)

    5.2 創建一個spring工程

    首先,創建一個基本的maven工程。
    配置pom文件,導入jar包

    <dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.0.RELEASE</version></dependency>

    創建配置文件bean.xml

  • 創建配置文件
  • 導約束
  • 把對象的創建交給spring來管理
  • <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!--把對象的創建交給spring來管理--><bean id="accountService" class="com.ssm.service.impl.AccountServiceImpl" ></bean><bean id="accuountDao" class="com.ssm.dao.impl.AccountDao"></bean></beans>

    Client的配置

    public class Client {public static void main(String[] args){ApplicationContext applicationContext = null;applicationContext = new ClassPathXmlApplicationContext("bean.xml");//兩種獲取實例的方式IAccountService as = (IAccountService) applicationContext.getBean("accountService");IAccountDao accountDao = applicationContext.getBean("accuountDao",IAccountDao.class);System.out.println(as);System.out.println(accountDao);} }

    ApplicationContext的三個實現類:

  • ClassPathXmlApplicationContext:加載類路徑下的配置文件,要求配置文件必須在類路徑下。否則加載不了。
  • FileSystemXmlApplicationContext:加載磁盤任意路徑下的配置文件(必須要有訪問權限)
  • AnnotationConfigApplicationContext:用于讀取注解創建容器。
  • 5.3 Spring是如何加載配置文件(Spring是什么時候實例化對象的)

    前面說過,Spring的IOC指的是Spring代替Application管理我們的JavaBean。那么他是什么時候實例化這些JavaBean的呢?
    一般有兩種情況

    • 一次性創建所有的對象,就是說Spring一次性實例化所有的對象
    • 按需要加載對象,就是說需要哪個對象,Spring再來幫我們實例化它

    這就對應著Spring核心容器的兩個接口,ApplicationContext和 BeanFactory。其中

    • ApplicationContext:構建核心容器時,創建對象采取的策略是立即加載的方式。讀完配置文件就創建配置文件中的對象。
    • BeanFactory:構建核心容器時,創建對象采取的策略是延遲加載的方式。什么時候根據id獲取對象,什么時候創建對象。
      實驗代碼
    public static void main(String[] args){ // ApplicationContext applicationContext = null; applicationContext = new FileSystemXmlApplicationContext(""); applicationContext = new AnnotationConfigApplicationContext(""); // applicationContext = new ClassPathXmlApplicationContext("bean.xml"); // // //兩種獲取實例的方式 // IAccountService as = (IAccountService) applicationContext.getBean("accountService"); // IAccountDao accountDao = applicationContext.getBean("accuountDao",IAccountDao.class); // // System.out.println(as); // System.out.println(accountDao);//==============使用BeanFactory創建對象==============BeanFactory factory = null;Resource rs = new ClassPathResource("bean.xml");factory = new XmlBeanFactory(rs);IAccountService as = (IAccountService) factory.getBean("accountService");System.out.println(as);}

    對應的AccountServiceImpl代碼

    public class AccountServiceImpl implements IAccountService {private IAccountDao accountDao = new AccountDao();//重寫構造器,看看該對象是什么時候創建的public AccountServiceImpl(){System.out.println("AccountServiceImpl被實例化了!");}public void saveAccount(){accountDao.saveAccount();} }

    6. Spring對bean的管理

    6.1 創建bean的三種方式

    6.1.1 使用默認構造函數創建bean

    在spring的配置文件中使用<bean></bean>標簽,配以id和class屬性,并且標簽中沒有其他屬性的時候。采用的就是默認類的構造函數創建bean對象。

    <bean id="accountService" class="com.ssm.service.impl.AccountServiceImpl" ></bean>

    此時如果AccountServiceImpl沒有默認構造函數(構造函數被重寫了),則無法創建對象。
    報錯,沒有發現默認的構造器。

    Failed to instantiate [com.ssm.service.impl.AccountServiceImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.ssm.service.impl.AccountServiceImpl.<init>()
    6.1.2 使用普通工廠中的方法創建對象

    假設一個情景
    如果我們現在要用第三方jar包中的某個類,但是這個類的構造函數被重寫了。那么我們該如何實例化這個類?
    比如上面的AccountServiceImpl沒有默認的構造函數,如何實例化它呢?

    此時需要借助一個工廠類InstanceFactory,通過它來實例化我們的對象。

    package com.ssm.factory;import com.ssm.service.IAccountService; import com.ssm.service.impl.AccountServiceImpl;public class InstanceFactory {public IAccountService getAccountService(){return new AccountServiceImpl("用工廠實例化AccountServiceImpl");} } <bean id="instanceFactory" class="com.ssm.factory.InstanceFactory"></bean><bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>

    過程是先實例化instanceFactory,再調用instanceFactory中的getAccountService方法。

    6.1.3 使用工廠中的靜態方法創建對象

    與上面的類似,只是不需要實例化工廠類了。直接調用工廠類中的靜態方法。具體如下

    <!--使用工廠中的靜態方法創建對象--><bean id="accountService" class="com.ssm.factory.StaticFactory" factory-method="getAccountService"></bean> package com.ssm.factory;import com.ssm.service.IAccountService; import com.ssm.service.impl.AccountServiceImpl;public class StaticFactory {public static IAccountService getAccountService(){return new AccountServiceImpl("使用靜態方法實例化AccountServiceImpl");} }

    可以在沒有實例化StaticFactory情況下,使用它創建一個AccountServiceImpl對象。

    回顧下static的知識 在Java類中,有六種成員:屬性、方法、構造器、初始化塊、內部類和枚舉類,其中static可以修飾屬性、方法、初始化塊、內部類和枚舉類。 以static修飾的的成員就是類成員。類成員屬于整個類,而不是單個對象。所以上面可以無需實例化StaticFactory 來創建AccountServiceImpl。因為類方法在類加載到jvm的時候就可以用了。

    6.2 bean的作用范圍

    bean標簽有一個scope屬性:用于指定bean的作用范圍。

    取值作用
    singleton單例(默認值)
    prototype多例
    request作用于web應用的請求范圍
    session作用于web應用的會話范圍
    global-session作用于集群環境的會話范圍(全局會話范圍),當不是集群環境時,等價于session

    6.3 bean的生命周期

    單例對象:我與容器共生死!!!
    多例對象:
    出生:使用對象時,由spring框架為我們創建
    或者:只要是使用,就一直活著
    死亡:長時間不用,且沒有別的對象引用,有GC負責回收

    實驗,單例對象

    <bean id="accountService" class="com.ssm.service.impl.AccountServiceImpl" scope="singleton" init-method="init" destroy-method="destory"></bean> public class AccountServiceImpl implements IAccountService {//private IAccountDao accountDao = new AccountDao();public AccountServiceImpl(){System.out.println("AccountServiceImpl被實例化了!");}public void saveAccount(){System.out.println("保存賬戶成功!");//accountDao.saveAccount();}public void init(){System.out.println("AccountServiceImpl對象創建了");}public void destory(){System.out.println("AccountServiceImpl對象銷毀了");} }Client片段public static void main(String[] args) throws Exception{ClassPathXmlApplicationContext applicationContext = null; // applicationContext = new FileSystemXmlApplicationContext(""); // applicationContext = new AnnotationConfigApplicationContext("");applicationContext = new ClassPathXmlApplicationContext("bean.xml");//兩種獲取實例的方式IAccountService as = (IAccountService) applicationContext.getBean("accountService");System.out.println(as);as.saveAccount();//手動關閉容器applicationContext.close();Thread.sleep(3000);}

    結果:

    spring創建時,先調用構造器,在調用init-method對應的方法,摧毀時調用destroy-method對應的方法

    總結

    以上是生活随笔為你收集整理的spring框架搭建第一天的全部內容,希望文章能夠幫你解決所遇到的問題。

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