Spring學習筆記

 

Spring 的控制反轉:把對象的建立、初始化、銷燬等工做交給Spring 容器來作,有spring容器控制對象的生命週期java

 

applicationContext.xml程序員

beans --->spring 容器中的類web

alias—>取別名spring

 

無論有繼承關係(無論有幾層)先把當前類加載到虛擬機中才能建立對象,而在加載過程當中,靜態代碼塊(static )就一塊執行了。因此express

如今子類靜態代碼快賦值,在父類中(@before)接受並使用該值編程

不管兩個類之間有什麼繼承關係,今天代碼塊比方法先執行。tomcat

--------------------------------------------------------------------------------------------------------------------------------------------------------安全

在默認狀況下,Spring建立bean是單例模式,屬性是共享的(線程安全問題)服務器

bean scope屬性--->singleton(單例,共享,默認)通常狀況下,把數據存放在方法中的變量中,儘可能別放在類的屬性中\prototype(多例) 當一個bean是多例模式下,lazy-init爲false或者default無效app

 

init-method
                     * 該方法是由spring容器執行
                     * 在構造函數以後執行
                     * 若是在構造函數以後,在調用方法以前要作一些工做,能夠在init方法中完成
destroy-method
                     * 若是該bean是單例,則在spring容器關閉或者銷燬的時候,執行該方法
                     * 若是該bean是多例,則spring容器不負責銷燬
                   說明:要想讓spring容器控制bean的生命週期,那麼該bean必須是單例
                              若是該bean是多例,該bean中還有資源,關閉資源的操做由程序員完成

 

在啓動spring容器的時候,spring容器配置文件中的類就已經建立完成對象了
                lazy-init
                   default  false
                   true  在context.getBean的時候纔要建立對象
                      *  優勢
                                    若是該bean中有大數據存在,則何時context.getBean,何時建立對象
                                    能夠防止數據過早的停留在內存中,作到了懶加載
                      *  缺點
                                     若是spring配置文件中,該bean的配置有錯誤,那麼在tomcat容器啓動的時候,發現不了
                   false 在啓動spring容器的時候建立對象
                      *  優勢
                                     若是在啓動tomcat時要啓動spring容器,
                                     那麼若是spring容器會錯誤,這個時候tomcat容器不會正常啓動
                      *  缺點
                                      若是存在大量的數據,會過早的停留在內存中

DI(依賴注入):給屬性賦值 person類中name;

eg、

<?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-2.5.xsd">
    <bean id="person" class="cn.itcast.spring0909.di.xml.set.Person">
        <!--
            property就是表明屬性
              在spring中基本類型(包裝類型和String)均可以用value來賦值
                                     引用類型用ref賦值

         -->
        <property name="pid" value="5"></property>
        <property name="pname" value="王二麻子"></property>
        <property name="student">
            <ref bean="student"/>
        </property>
        <property name="lists">
            <list>
                <value>list1</value>
                <value>list2</value>
                <ref bean="student"/>
            </list>
        </property>
        <property name="sets">
            <set>
                <value>set1</value>
                <value>set2</value>
                <ref bean="student"/>
            </set>
        </property>
        <property name="map">
            <map>
                <entry key="map1">
                    <value>map1</value>
                </entry>
                <entry key="map2">
                    <value>map2</value>
                </entry>
                <entry key="map3">
                    <ref bean="student"/>
                </entry>
            </map>
        </property>
        <property name="properties">
            <props>
                <prop key="prop1">
                    prop1
                </prop>
            </props>
        </property>
    </bean>
    <bean id="student" class="cn.itcast.spring0909.di.xml.set.Student"></bean>
</beans>

構造函數:

<bean id="person" class="cn.itcast.spring0909.di.xml.constructor.Person">
        <!--
            構造函數的參數
              index  第幾個參數,下標從0開始
              type   參數的類型
              ref    若是類型是引用類型,賦值
              value  若是類型是基本類型,賦值
             說明:
                只能指定一個構造函數
         -->
        <constructor-arg index="0"  type="java.lang.String" value="幹露露"></constructor-arg>
        <constructor-arg index="1"  ref="student"></constructor-arg>
    </bean>

 

IOC和DI作了什麼事情:

一、建立對象

二、爲對象的屬性賦值

意義在於:能夠在一個類引用一個接口,而給接口賦值的工做交給spring容器來作,程序員只需在配置文件做相應的配置就行了,這樣客戶端就能夠徹底的面向接口的編程。

----------------------------------------------------------------------------------------------------------------------------------------------

annotation

@Resource註解

原理
*    *  啓動spring容器,而且加載配置文件
*    *  會爲student和person兩個類建立對象
*    *  當解析到<context:annotation-config></context:annotation-config>
*       會啓動依賴注入的註解解析器
*    *  會在歸入spring管理的bean的範圍內查找看哪些bean的屬性上有@Resource註解
*    *  若是@Resource註解的name屬性的值爲"",則會把註解所在的屬性的名稱和spring容器中bean的id進行匹配
*       若是匹配成功,則把id對應的對象賦值給該屬性,若是匹配不成功,則按照類型進行匹配,若是再匹配不成功,則報錯
*    *  若是@Resource註解的name屬性的值不爲"",會把name屬性的值和spring容器中bean的id作匹配,若是匹配
*       成功,則賦值,若是匹配不成功 ,則直接報錯
* 說明:
*    註解只能用於引用類型,若是一個類中有基本數據類型(long int String),而且基本類型使用Spring的形式賦值的,這個時候,該類必須用xml進行賦值(在javaweb中不多直接賦值,大多數都是從服務器獲取值)

 

@component註解

原理
*   *  啓動spring容器,加載配置文件
*   *  spring容器解析到
*         <context:component-scan base-package="cn.itcast.spring0909.scan"></context:component-scan>
*   *  spring容器會在指定的包及子包中查找上是否有@Component
*   *  若是@Component註解沒有寫任何屬性
*        @Component
*        public class Person{
*       
*        }
*        ==
*        <bean id="person" class="..Person">
*      若是@Component("aa")
*        @Component
*        public class Person{
*       
*        }
*        ==
*        <bean id="aa" class="..Person">
*    *  在歸入spring管理的bean的範圍內查找@Resource註解
*    *  執行@Resource註解的過程
*  說明:
*     xml效率比較高,可是書寫比較麻煩
*     註解效率比較低,書寫比較簡單

-------------------------------------------------------------------------------------------------------------------------------------

<!--
        abstract
          spring容器不會爲該類建立對象
     -->
    <bean id="person" class="cn.itcast.spring0909.extend.Person" abstract="true">
        <property name="name" value="王二麻子的哥"></property>
    </bean>

--------------------------------------------------

<bean id="person" class="cn.itcast.spring0909.extend.Person" abstract="true">
        <property name="name" value="王二麻子的哥"></property>
    </bean>
    <!--
        parent
          讓子類擁有父類的屬性的值
     -->
    <bean id="student" class="cn.itcast.spring0909.extend.Student" parent="person">
    </bean>

 

 

代理模式、動態代理  (invoke)

package cn.itcast.salary.jdkproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
 * 一、把日誌、安全性框架、權限導入進去
 * 二、把目標類導入進去
 * 三、上述兩類經過構造函數賦值
 * @author Administrator
 *
 */
public class SalaryInterceptor implements InvocationHandler{
    
    private Logger logger;
    private Security security;
    private Privilege privilege;
    
    private Object target;
    
    public SalaryInterceptor(Logger logger,Security security,Privilege privilege,Object target){
        this.logger = logger;
        this.security = security;
        this.privilege = privilege;
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        // TODO Auto-generated method stub
        System.out.println("aaaaaa");
        this.logger.logging();
        this.security.security();
        if("admin".equals(this.privilege.getAccess())){
            //調用目標類的目標方法
            method.invoke(this.target, args);
        }else{
            System.out.println("您沒有該權限");
        }
        System.out.println("bbbbbb");
        return null;
    }

}
客戶端
public void test(){
        Logger logger = new Logger();
        Privilege privilege = new Privilege();
        privilege.setAccess("admin");
        Security security = new Security();
        SalaryManager target = new SalaryManagerImpl();
        SalaryInterceptor interceptor = new SalaryInterceptor(logger, security, privilege, target);
        /**
         * 一、目標類的類加載器
         * 二、目標類的全部的接口
         * 三、攔截器
         */
         SalaryManager proxy = (SalaryManager) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), interceptor);
         proxy.showSalary();//代理對象的代理方法
    }

---------------------------------------------------------------------------------------------------------------

image

image

---------------------------------------------------------------------------------------------------------------------

AOP

image

 

捕獲

 

說明:

* 切面

日誌、安全性的框架、權限的檢查等,總之和業務邏輯沒有關係的均可以看作切面

* 通知

切面中的方法

* 切入點

只有符合切入點,才能把通知和目標方法結合在一塊兒

* 鏈接點

客戶端調用的方法

* 代理對象的方法=通知+目標方法

* aop:作到了代碼塊的重用

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop"
    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-2.5.xsd
           http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
    <!-- 
        一、引入AOP的命名空間
        二、目標類
        三、切面
        四、攔截器  由spring內部實現
        五、aop的配置
     -->
    <bean id="personDao" class="cn.itcast.spring0909.aop.xml.PersonDaoImpl"></bean>
    <bean id="transaction" class="cn.itcast.spring0909.aop.xml.Transaction"></bean>
    <!-- 
        aop的配置
     -->
    <aop:config>
        <!-- 
            切入點表達式
              expression
                     肯定哪一個類能夠生成代理對象
              id  惟一標識 
         -->
        <aop:pointcut expression="execution(* cn.itcast.spring0909.aop.xml.PersonDaoImpl.*(..))" id="perform"/>
        <!-- 
            切面
         -->
         <aop:aspect ref="transaction">
             <!-- 
                 前置通知
              -->
             <aop:before method="beginTransaction" pointcut-ref="perform"/>
             <aop:after-returning method="commit" pointcut-ref="perform"/>
         </aop:aspect>
    </aop:config>
</beans>

 

QQ截圖20150401220728

------------------------------------------------------------------------------------------------------

 

<aop:config>
        <!-- 
            切入點表達式
              expression
                     肯定哪一個類能夠生成代理對象
              id  惟一標識 
         -->
        <aop:pointcut expression="execution(* cn.itcast.spring0909.aop.xml.PersonDaoImpl.*(..))" id="perform"/>
        <!-- 
            切面
         -->
         <aop:aspect ref="transaction">
             <!-- 
                 前置通知
                   *  在目標方法執行以前
                   *  
              -->
              <!-- 
             <aop:before method="beginTransaction" pointcut-ref="perform"/>
              -->
             <!-- 
                 後置通知
                   *  在目標方法執行以後
                   *  能夠根據returning獲取目標方法的返回值
                   *  若是目標方法遇到異常,該通知不執行
              -->
              <!-- 
             <aop:after-returning method="commit" pointcut-ref="perform" returning="val"/>
              -->
            <!-- 
                前置通知和後置通知只能在目標方法文中添加內容,可是控制不了目標方法的執行
             -->
             <!-- 
                 最終通知
                    *  在目標方法執行以後
                    *  不管目標方法是否遇到異常,都執行
                    *  常常作一些關閉資源
              -->
              <!-- 
             <aop:after method="finallyMethod" pointcut-ref="perform"/>
              -->
             <!-- 
                 異常通知
                    目的就是爲了獲取目標方法拋出的異常
              -->
              <aop:after-throwing method="exceptionMethod" throwing="ex" pointcut-ref="perform"/>
              <!-- 
                  環繞通知
                     能控制目標方法的執行
               -->
              <aop:around method="aroundMethod" pointcut-ref="perform"/>
         </aop:aspect>
    </aop:config>

 

AOP總結:

* 原理
*    *  加載配置文件,啓動spring容器
*    *  spring容器爲bean建立對象
*    *  解析aop的配置,會解析切入點表達式
*    *  看歸入spring管理的那個類和切入點表達式匹配,若是匹配則會爲該類建立代理對象
*    *  代理對象的方法體的造成就是目標方法+通知
*    *  客戶端在context.getBean時,若是該bean有代理對象,則返回代理對象,若是沒有代理對象則返回原來的對象
* 說明:
*    若是目標類實現了接口,則spring容器會採用jdkproxy,若是目標類沒有實現接口,則spring容器會採用
*      cglibproxy

---------------------------------------------------------------------------------------------------------------------------------------------

Struts2

問題:

* action是單例仍是多例?怎麼樣證實?

Action是多例的,在構造函數中輸出一句話,若是請求好幾回,只輸出一次,單例

若是請求不少次,輸出不少次,多例

* struts2有三個類

ActionContext

ServletActionContext 創建struts2與servlet的通訊的橋樑

ActionInvocation struts2總的上下文

* struts2的數據都在值棧中,怎麼樣保證數據的安全性?值棧的生命週期是什麼?

由於ValueStack在ActionContext中,而ActionContext在ThreadLoad中,因此能夠保證數據的安全性

值棧的生命週期是一次請求,當前的action,actioncontext,valuestack的生命週期是一致的

 

image

 

 

--------------------------------------------------------------------------------------------------------

image

 

image

相關文章
相關標籤/搜索