spring01

1.  Spring的概述

1.1. 什麼是Spring

    Spring分層的、JavaSE/EE一站式(full-stack)輕量級開源框架java

JavaEE分層:JavaEE規範的三層結構體系web

1.表現層(頁面數據顯示、頁面跳轉調度),例如jsp/servletspring

2.業務層(業務處理和功能邏輯、事務控制),例如service數據庫

3.持久層(數據存取和封裝、和數據庫打交道),例如dao編程

如圖:設計模式

一站式:Spring提供了JavaEE各層的解決方案:數組

表現層:struts1struts2Spring MVC緩存

業務層:IocAOP、事務控制服務器

持久層:JdbcTemplateHibernateTemplateORM框架(對象關係映射)整合架構

 

輕量級Spring的出現取代了EJB的臃腫、低效、繁瑣複雜、脫離現實的狀況. 並且使用spring編程是非侵入的。

 

1.2.  Spring的體系結構

 Spring框架是一個分層架構,它包含一系列的功能要素並被分爲大約20個模塊。這些模塊分爲Core ContainerData Access/IntegrationWebAOPAspect Oriented Programming)、Instrumentation和測試部分

核心容器(Core Container) 包括Core、Beans、Context、EL模塊。
1:Core和Beans模塊提供了Spring最基礎的功能,提供IoC和依賴注入特性。這裏的基礎概念是BeanFactory,它提供對Factory模式的經典實現來消除對程序性單例模式的須要,並真正地容許你從程序邏輯中分離出依賴關係和配置。
2:Context模塊基於Core和Beans來構建,它提供了用一種框架風格的方式來訪問對象,有些像JNDI註冊表。Context封裝包繼承了beans包的功能,還增長了國際化(I18N),事件傳播,資源裝載,以及透明建立上下文,例如經過servlet容器,以及對大量JavaEE特性的支持,如EJB、JMX。核心接口是ApplicationContext。
3:Expression Language,表達式語言模塊,提供了在運行期間查詢和操做對象圖的強大能力。支持訪問和修改屬性值,方法調用,支持訪問及修改數組、容器和索引器,命名變量,支持算數和邏輯運算,支持從Spring 容器獲取Bean,它也支持列表投影、選擇和通常的列表聚合等。

數據訪問/集成部分(Data Access/Integration)
1:JDBC模塊,提供對JDBC的抽象,它可消除冗長的JDBC編碼和解析數據庫廠商特有的錯誤代碼。
2:ORM模塊,提供了經常使用的"對象/關係"映射APIs的集成層。 其中包括JPA、JDO、Hibernate 和 iBatis 。利用ORM封裝包,能夠混合使用全部Spring提供的特性進行"對象/關係"映射,如簡單聲明性 事務管理 。
3:OXM模塊,提供一個支持Object和XML進行映射的抽象層,其中包括JAXB、Castor、XMLBeans、JiBX和XStream。
4:JMS模塊,提供一套"消息生產者、消費者"模板用於更加簡單的使用JMS,JMS用於用於在兩個應用程序之間,或分佈式系統中發送消息,進行異步通訊。
5:Transaction模塊,支持程序經過簡單聲明性 事務管理,只要是Spring管理對象都能獲得Spring管理事務的好處,即便是POJO,也能夠爲他們提供事務。

Web
1:Web模塊,提供了基礎的web功能。例如多文件上傳、集成IoC容器、遠程過程訪問、以及Web Service支持,並提供一個RestTemplate類來提供方便的Restful services訪問
2:Web-Servlet模塊,提供了Web應用的Model-View-Controller(MVC)實現。Spring MVC框架提供了基於註解的請求資源注入、更簡單的數據綁定、數據驗證等及一套很是易用的JSP標籤,徹底無縫與Spring其餘技術協做。
3:Web-Struts模塊, 提供了對Struts集成的支持,這個功能在Spring3.0裏面已經不推薦了,建議你遷移應用到使用Struts2.0或Spring的MVC。
4:Web-Portlet模塊,提供了在Portlet環境下的MVC實現

AOP
1:AOP模塊,提供了符合AOP 聯盟規範的面向方面的編程實現,讓你能夠定義如方法攔截器和切入點,從邏輯上講,能夠減弱代碼的功能耦合,清晰的被分離開。並且,利用源碼級的元數據功能,還能夠將各類行爲信息合併到你的代碼中 。
2:Aspects模塊,提供了對AspectJ的集成。
3:Instrumentation模塊, 提供一些類級的工具支持和ClassLoader級的實現,能夠在一些特定的應用服務器中使用。

Test
1:Test模塊,提供對使用JUnit和TestNG來測試Spring組件的支持,它提供一致的ApplicationContexts並緩存這些上下文,它還能提供一些mock對象,使得你能夠獨立的測試代碼。

 

1.3.  Spring的核心

IoCInverse of Control 控制反轉):將對象建立權利交給Spring工廠進行管理。好比說:Book book = new Book();  Book book2 = Spring工廠.getBook();

AOPAspect Oriented Programming 面向切面編程),基於動態代理的功能加強方式。

 

1.4.  Spring的優勢

Spring 出現爲了解決JavaEE 實際問題 
(1)方便解耦,簡化開發
Spring就是一個大工廠,它能夠將全部對象建立和依賴關係維護,交給Spring管理
(2)AOP編程的支持
Spring提供面向切面編程,能夠方便的實現對程序進行權限攔截、運行監控等功能
(3)聲明式事務的支持
只須要經過配置就能夠完成對事務的管理,而無需手動編程
(3)方便程序的測試
Spring對Junit4支持,能夠經過註解方便的測試Spring程序
(5)方便集成各類優秀框架
Spring不排斥各類優秀的開源框架,其內部提供了對各類優秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持
(6)下降JavaEE API的使用難度
Spring 對JavaEE開發中很是難用的一些API(JDBC、JavaMail、遠程調用等),都提供了封裝,使這些API應用難度大大下降

關於框架的特性,咱們也會俗稱Spring爲開發架構的粘合劑

 

1.5.  IoC控制反轉

採用IoCInverse of Control,控制反轉)的思想解決代碼耦合問題。

簡單的說就是引入工廠(第三者),將原來在程序中手動建立管理的依賴的UserDaoImpl對象,交給工廠來建立管理。

IoC底層實現:工廠(設計模式)+反射(機制) + 配置文件(xml)。

 

1.1.  DI依賴注入的實現

DIDependency Injection 依賴注入,在Spring框架負責建立Bean對象時,動態的將依賴對象注入到Bean組件(簡單的說,能夠將另一個bean對象動態的注入到另一個bean中。)

回顧以前的代碼:

步驟一:service對象也交給spring容器管理

applicationContext.xml

<?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/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- bean: spring工廠建立的一個對象(反射機制)
    id/name:對象的名字,能夠用來引用或者獲取對象, 通常爲類名或接口名稱的首字母小寫
    class:要建立的對象類型的類字符串,類名全路徑
 -->
<bean id="userDAO" class="cn.spring.a_quickstart.UserDAOImpl" />

<bean id ="userService" class="cn.spring.a_quickstart.UserServiceImpl">
    <!-- 注入對象 -->
    <!-- property 根據類中的setter方法進行屬性注入 -->
    <!-- name:類中setter方法的後綴小寫,好比setXxx 對應的name爲xxx -->
    <!-- ref:引用哪個bean(對象),值爲bean的id/name -->
    <property name="userDAO" ref="userDAO" />
</bean>
</beans>

步驟二:在程序中定義屬性提供setter方法:

UserServiceImpl.java

public class UserServiceImpl implements IUserService{
    
    //定義屬性
    private IUserDAO userDAO;

    public void setUserDAO(IUserDAO userDAO) {
        this.userDAO = userDAO;
    }

    public void login() {
         System.out.println("UserServiceImpl-service層方法調用了");
         
         //ioc:依賴注入
         userDAO.findUserByUsernameAndPassword();
        
    }

步驟:Dao

//dao的實現類
public class UserDaoImpl implements IUserDao {
    @Override
    public void findByUsernameAndPassword() {
        System.out.println("UserDaoImpl-dao層被調用了");
    }
}

步驟:測試運行,此時獲取對象必須從spring工廠獲取(spring容器配置中才有依賴注入,本身建立的對象沒有注入依賴關係)

public class SpringTest {
    //測試
    @Test
    public void test(){
        //建立service的示例
        //IUserService userService = new UserServiceImpl();
        //userService.login();
        
        //建立spring工廠,獲取spring管理的對象
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        IUserService userService = (IUserService) ac.getBean("userService");
    
        userService.login();
    }
}

小結:

IOC:控制反轉,將對象建立管理的權利交給spring容器,獲取對象經過spring工廠建立

DI:spring容器中建立管理多個對象,經過 property標籤將對象注入到須要依賴的對象中

 

【擴展】

Bean獲取的兩種方式:

    @Test
    public void getBean(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        //獲取bean的兩種方式
        //1.經過spring容器中bean的id/name獲取
        //IUserService userService = (IUserService) ac.getBean("userService");
        
        //2.根據bean的類型或者bean接口的類型獲取,通常使用接口類型
        IUserService userService = (IUserService) ac.getBean(IUserService.class);
        userService.login();
    }

經常使用根據名稱獲取(id/name,即第一種方式,使用spring容器中的標識獲取對象

方式二的弊端:若是根據類型獲取,配置了多個類型的話,則拋出異常:

applicationContext.xml

<bean id ="userService1" class="cn..spring.a_quickstart.UserServiceImpl">
    <property name="userDAO" ref="userDAO" />
</bean>

<bean id ="userService2" class="cn.spring.a_quickstart.UserServiceImpl">
    <property name="userDAO" ref="userDAO" />
</bean>

 

2.  IoC容器裝配Bean_基於XML配置方式

2.1.  實例化Bean的四種方式 (瞭解)

第一種方式 無參數構造器 (最經常使用)

第一步:建立Bean1.java

//1。默認構造器(spring在建立bean的時候自動調用無參構造器來實例化,至關於new Bean1())
public class Bean1 {
}

第二步:在spring容器applicationContext.xml中配置

<!-- 實例化 bean的四種方式 -->
    <!-- 1.默認構造器實例化對象 -->
    <bean id ="bean1" class="cn.spring.b_xmlnewbean.Bean1" />

第三步:建立測試類獲取bean對象

SpringTest.java:

public class SpringTest {
    @Test
    public  void test(){
        //建立spring工廠
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //1.默認構造器獲取bean對象
        Bean1 bean1 = (Bean1) ac.getBean("bean1");
        System.out.println(bean1);
    }
}

【錯誤演示】:

public class Bean1 {
    //錯誤演示
    private String name;
    
    public Bean1(String name) {
        this.name = name;
    }
}

 靜態工廠方法、 實例工廠方法、FactoryBean方式這三種方式在這裏就不演示了,第一種是最經常使用的

 

2.2.  Bean的做用域 

spring建立的bean對象在什麼狀況下有效。

項目開發中一般會使用:singleton 單例、 prototype多例

Singleton: 在一個spring容器中,對象只有一個實例。(默認值

Prototype: 在一個spring容器中,存在多個實例,每次getBean 返回一個新的實例

 

第一步:建立類SingletonBean.javaPrototypeBean.java

建立類SingletonBean.java

//單例bean
public class SingletonBean {
    public SingletonBean() {
        System.out.println("SingletonBean:初始化了單例");
    }
}

建立類PrototypeBean.java

//多例bean
public class PrototypeBean {
    public PrototypeBean() {
        System.out.println("--PrototypeBean初始化了多例的");
    }
}

第二步:applicationContext配置文件:

   <!-- 
        bean的做用範圍
        scope:配置做用範圍的,默認值就是singleton單例
     -->
    <!-- 單例 -->
    <bean id="singletonBean" class="cn.spring.c_xmlscope.SingletonBean" scope="singleton"/> 
    <bean id="singletonBean" class="cn.spring.c_xmlscope.SingletonBean"/>
    <!-- 多例 -->
    <bean id="prototypeBean" class="cn.spring.c_xmlscope.PrototypeBean" scope="prototype"/>

第三步:測試代碼,建立SpringTest.java

//newbean的方式
public class SpringTest {
    
    @Test
    public void test(){
        //先構建實例化獲取spring的容器(工廠、上下文)
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //目標1:看看屢次獲取bean的時候,是否是同一個
        //目標2:看看bean何時初始化的
        //獲取單例的bean:應該是同一個
        //單例:每次從spring容器中獲取的對象,是同一個對象
        //單例初始化:是在spring容器初始化的時候,就初始化了
        //即這一步new ClassPathXmlApplicationContext("applicationContext.xml")就初始化單例了
        SingletonBean singletonBean1=(SingletonBean)applicationContext.getBean("singletonBean");
        SingletonBean singletonBean2=(SingletonBean)applicationContext.getBean("singletonBean");
        System.out.println(singletonBean1);
        System.out.println(singletonBean2);
        //獲取多例的bean:
        //多例:每次從spring容器中獲取的對象,不是同一個對象
        //多例初始化:是在getBean的時候初始化,至關於每次getbean就是在new Bean()
        PrototypeBean prototypeBean1=(PrototypeBean)applicationContext.getBean("prototypeBean");
        PrototypeBean prototypeBean2=(PrototypeBean)applicationContext.getBean("prototypeBean");
        System.out.println(prototypeBean1);
        System.out.println(prototypeBean2);
    }
}

【注意】

單例是默認值,若是須要單例對象,則不須要配置scope

 

3.  IoC容器裝配Bean_基於註解配置方式

第二步 編寫ServiceDAO 的註冊

 xml作法 : <bean id=」customerService」 class=」…」 />,用<bean>的方式建立對象

註解作法 spring2.5引入 @Component 註解 若是放置到類的上面,至關於在spring容器中定義<bean id=」」 class=」」>

建立類:CustomerService.java

/**
 * @Component註解放置到類上
 * 至關於spring容器中定義:<bean id="customerService" class="cn.spring.a_ioc.CustomerService">
 * @Component(value="customerService")  //能夠自定義bean的id名字
   若是不寫value值,默認value值爲類名的首字母小寫,即customerService
 * 至關於spring容器中定義:<bean id="customer" class="cn.spring.a_ioc.CustomerService">
 */

//注意:只有value一個屬性時,能夠寫做@Component("customerService"),也能夠寫做@Component
@Component(value="customerService")
public class CustomerService {
    //保存業務方法
    public void save(){
        System.out.println("CustomerService業務層被調用了。。。");
    }
}

第三步: 配置註解開啓和註解Bean的掃描。配置的示例以下:配置applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                              http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context 
                           http://www.springframework.org/schema/context/spring-context.xsd">
    
    <!-- 開啓spring的註解功能 :讓註解有效了,識別註解-->
    <context:annotation-config/>

    <!-- 配置註解bean掃描 
            context:component-scan:專門掃描含有@Component註解的類,自動將其做爲bean
            base-package:要掃描包的路徑,cn.itcast.spring全部子包下的全部類定義註解都有效
            注意:配置註解ean掃描時,會自動開啓註解功能,全部若是配置註解掃描能夠不配置開啓註解功能
    -->
    <context:component-scan base-package="cn.itcast.spring"/>
</beans>

擴展優化:

1.註解掃描配置

配置註解掃描時,會自動開啓註解功能,全部若是配置註解掃描能夠不配置開啓註解功能

2.衍生註解的問題

實際開發中,使用的是@Component三個衍生註解(「子註解」)

子註解的做用:有分層的意義(分層註解)。

Spring3.0爲咱們引入了組件自動掃描機制,它能夠在類路徑底下尋找標註了@Component、@Service、@Controller、@Repository註解的類,
並把這些類歸入進spring容器中管理。
除了@Component外,Spring提供了3個功能基本和@Component等效的註解

功能介紹
@Service用於標註業務層組件(如Service層)
@Controller用於標註控制層組件(如struts中的action層)
@Repository用於標註數據訪問組件,(如DAO層組件)。
而@Component泛指組件,當組件很差歸類的時候,咱們可使用這個註解進行標註。(好比測試類)
相關文章
相關標籤/搜索