Spring框架的學習(第二天)

xml文件導入其他xml文件配置

如果我們在spring框架中配置了多個xml文件,我們可以在讀取配置文件的時候把這些xml文件一下全都讀取,也可以只讀一個總的xml文件,在這個總的xml文件中把其他的xml全都都導入進來。
例如:

student.xml文件:

<bean name="student" class="com.briup.bean.Student">
    <property name="id">
        <value>25</value>
    </property>
</bean>

teacher.xml文件:

<bean name="teacher" class="com.briup.bean.Teacher">
        <property name="student" ref="student"></property>//ref=""手動注入哪個bean
</bean>

import.xml文件:

<import resource="teacher.xml"/>
<import resource="student.xml"/>

main:

String[] path = {"com/briup/ioc/imp/import.xml"};
ApplicationContext container = new ClassPathXmlApplicationContext(path);

Teacher t = (Teacher) container.getBean("teacher");
System.out.println(t.getStudent());

創(chuàng)建bean實例的方式

xml文件中有bean的配置,而且這個bean所對應的java類中存在一個無參構造器洞焙,那么這個時候spring容器就可以使用反射調用無參構造器來創(chuàng)建實例了

通過工廠類獲得實例(工廠類實現了接口FactoryBean<?>)

注意spring中的PropertyPlaceholderConfigurer類的使用,在htmlsingle中直接搜索類名即可

例如:
工廠類實現指定接口并且實現接口中的三個抽象方法:

    public class ConnectionFactory implements FactoryBean<Connection>{
    private String driver;
    private String url;
    private String username;
    private String password;

    @Override
    public Connection getObject() throws Exception {
        Class.forName(driver);
        Connection conn = 
            DriverManager.getConnection(url,username,password);
        return conn;
    }

    @Override
    public boolean isSingleton() {//判斷它是否是單例
        // TODO Auto-generated method stub
        return false;
    }
    
    @Override
    public Class<Connection> getObjectType() {
        // TODO Auto-generated method stub
        return Connection.class;
    }
    set/get
    ....
  }

xml文件:

因為這個類是一個工廠類,所以我們用名字conn在容器中拿對象的時候,拿到并不是這個工廠類對象,而是這個工廠類對象調用完工廠方法后所返回的對象.

  <bean name="conn" class="com.briup.ioc.factory.ConnectionFactory">
    <property name="driver">
        <value>${driver}</value>//從一個配置文件中以key—value的形式拿value
    </property>
    
    <property name="url">
        <value>${url}</value>
    </property>
    
    <property name="username">
        <value>${username}</value>
    </property>
    
    <property name="password">
        <value>${password}</value>
    </property>
  </bean>
  
  <!-- 
    下面配置的這個類,可以自動的幫我們去讀取指定的properties文件的
    內容,文件中用key-value的形式存放數據,讀完之后我們就可以用
    ${key}這種形式去拿文件中的value值了败明。
    classpath指的是從src下面找.
  -->
  <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location">
        <value>classpath:oracle.properties</value>
    </property>
  </bean>

main:

String path = "com/briup/ioc/factory/factory.xml";
ApplicationContext container = 
        new ClassPathXmlApplicationContext(path);
Connection conn = (Connection) container.getBean("conn");
System.out.println(conn);

通過實例工廠獲得實例(不需要實現或者繼承任何接口或者父類)

注意spring中的PropertyPlaceholderConfigurer類的使用,在htmlsingle中直接搜索類名即可

例如:一個普通的工程類

  public class ConnectionFactory{
    private String driver;
    private String url;
    private String username;
    private String password;
    
    public Object getConnection() throws Exception {
        Class.forName(driver);
        Connection conn = DriverManager.getConnection(url,username,password);
        return conn;
    }
    get/set
    ....
  }

  xml文件:
 <bean name="factory" class="com.briup.ioc.instanceFactory.ConnectionFactory">
    <property name="driver">
        <value>${driver}</value>
    </property>
    
    <property name="url">
        <value>${url}</value>
    </property>
    
    <property name="username">
        <value>${username}</value>
    </property>
    
    <property name="password">
        <value>${password}</value>
    </property>
 </bean>
    
 <!-- 
    將來通過這個conn來拿對象,拿到的是名字為factory的工廠類調用完
    名字為getConnection方法之后所返回的對象抡驼。
 -->
 <bean name="conn" factory-bean="factory" factory-method="getConnection"></bean>
 
 <!-- 讀取properties文件 -->
 <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location">
        <value>classpath:oracle.properties</value>
    </property>
 </bean>

main:

String path = "com/briup/ioc/instanceFactory/instanceFactory.xml";
ApplicationContext container = 
    new ClassPathXmlApplicationContext(path);
Connection conn = (Connection) container.getBean("conn");
System.out.println(conn);

通過靜態(tài)工廠獲得實例

例如:含義靜態(tài)方法的工廠類

  public class ConnectionFactory{
    private static String driver = "oracle.jdbc.driver.OracleDriver";
    private static String url = "jdbc:oracle:thin:@127.0.0.1:1521:XE";
    private static String username = "briup";
    private static String password = "briup";
    
    public static Object getConnection() throws Exception {
        Class.forName(driver);
        Connection conn = DriverManager.getConnection(url,username,password);
        return conn;
    }
  }

  xml文件:
  <!-- 這樣配置一定要求getConnection方法是靜態(tài)方法 -->
  <bean name="conn" class="com.briup.ioc.staticFactory.ConnectionFactory" factory-method="getConnection"></bean>

main:

String path = "com/briup/ioc/staticFactory/staticFactory.xml";
ApplicationContext container = new ClassPathXmlApplicationContext(path);
Connection conn = (Connection) container.getBean("conn");
System.out.println(conn);

自定義屬性編輯器 PropertyEditor

Spring中我們可以使用屬性編輯器來將特定的字符串轉換為對象 :String-->object java.beans.PropertyEditor(JDK中的接口)用于將xml文件中字符串轉換為特定的類型
同時JDK為我們提供一個實現類java.beans.PropertyEditorSupport
Spring在注入時,如果遇到類型不一致(例如需要Address類型但是用戶傳了個String)則會去調用相應的屬性編輯器進行轉換.
spring會調用屬性編輯器的setAsText(String str)進行處理用戶傳的字符串,并調用getValue()方法獲取處理后得到的對象,所以我們在代碼中處理完后記得調用setValue方法,要不然spring調用getValue方法拿不到你處理后的對象

自定義屬性編輯器示例

  1. //自定義編輯器類

     public class AddressEditor extends PropertyEditorSupport {
     @Override
     public String getAsText() {
         return super.getAsText();
     }
    
  2. //Spring遇到數據類型不一致并且不能自己處理的時候會調用這個方法處理字符串

     @Override
     public void setAsText(String text) throws IllegalArgumentException {
         String[] str = text.split(",");
         String city = str[0];
         String street = str[1];
         String country = str[2];
         Address add = new Address(city, street, country);
         setValue(add);
     }
    
     }
     //Address類
     public class Address {
     private String city;
     private String street;
     private String country;
     set/get
     .....
     }
    
     //Student類
     public class Student {
     private long id;
     private String name;
     private boolean gender;
     private int age;
     private Address address;
     get/set
     ...
     }
    

xml文件:

    <!-- 這個配置指明哪個類型對應哪個自定義編輯器 -->
    <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
    <property name="customEditors">
     <map>
    <entry key="com.briup.ioc.proEdit.Address"  value="com.briup.ioc.proEdit.AddressEditor"/>
</map>
    </property>
    </bean>
 <!-- spring發(fā)現address的值不能注入的時候(類型不對),就會調用對應的屬性編輯器處理了 -->
  <bean id="student" class="com.briup.ioc.proEdit.Student">
    <property name="id" value="1"/>
    <property name="name" value="tom"/>
    <property name="age" value="45"/>
    <property name="gender" value="true"/>
    <property name="address">
        <value>kunshan,xueyuan,China</value>
    </property>
 </bean>

自定義事件

在spring中我們可以自定義事件,并且可以使用ApplicationContext類型對象(就是spring容器container)來發(fā)布這個事件,事件發(fā)布之后,所有的ApplicaitonListener(監(jiān)聽器)實例都會被觸發(fā)并調用指定方法onApplicationEvent()來處理.

例如:
自定義事件類RainEvent:

public class RainEvent extends ApplicationEvent {
public RainEvent(Object source) {
    super(source);
}
}

監(jiān)聽器類RainListener1

public class RainListener1 implements ApplicationListener {
//這里需要加類型判斷笛粘,如果不加類型判斷的話只要是事件發(fā)生都會執(zhí)行監(jiān)聽器類這個
//方法恃泪,所以我們必須加上類型判斷外臂,當屬于我們自定義的那個類型的時候我們才進行處理坐儿。
public void onApplicationEvent(ApplicationEvent event) {
    if (event instanceof RainEvent) {
        System.out.println("唐僧大喊:" + event.getSource() + "趕快收衣服嘍!");
    }
 }

}
監(jiān)聽器類RainListener2

public class RainListener2 implements ApplicationListener {
public void onApplicationEvent(ApplicationEvent event) {
    if (event instanceof RainEvent) {
        System.out.println("我們:" + event.getSource() + "太好了不用上課了宋光!");
    }
 }

}

xml文件:

<!-- 只需要把這倆個監(jiān)聽器類交給spring容器管理就可以了 -->
<bean class="com.briup.ioc.event.RainListener1"></bean>
<bean class="com.briup.ioc.event.RainListener2"></bean>

main:

String path = "com/briup/ioc/event/event.xml";
ApplicationContext container = new ClassPathXmlApplicationContext(path);
//觸發(fā)條件
container.publishEvent(new RainEvent("下雨了貌矿!"));

ioc中的annotation配置

  1. @Autowired

  2. @Autowired默認按照byType匹配的方式進行注入,如果沒有一個bean的類型是匹配的則會拋異常,
    如果有多個bean的類型都匹配成功了,那么再按byName方式進行選擇

  3. @Autowired注解可以寫在成員變量、set/ger方法罪佳、構造器函數上面

  4. @Autowired如果最終匹配不成功(注意一定是一個都沒有找到的情況)則會拋出異常,
    但是如果設置為@Autowired(required=false),則最終匹配不成功沒有不會拋出異常逛漫。

  5. @Autowired可以結合 @Qualifier("beanName")來使用,則可以達到byName的效果

  6. @Autowired使用后需要在xml文件加入以下配置才能生效:
    <context:annotation-config/>(高版本的就不需要加 )

  7. @Resource

  8. @Resource的作用和 @Autowired差不多,只不過@Resource是默認先用byname,
    如果找不到合適的就再用bytype來注入

  9. Resource有倆個屬性,name和type,使用name屬性則表示要byName匹配,使用type屬性則表示要byType匹配

  10. @Resource使用后需要在xml文件加入以下配置才能生效:
    <context:annotation-config/>

  11. @PostConstruct 和 @PreDestroy

單例的類是有ApplicationContext管理。所以當ac.destory()時赘艳,類也就銷毀了酌毡。

  1. 標注了 @PostConstruct 注釋的方法將在類實例化后調用克握。
  2. 標注了 @PreDestroy 的方法將在類銷毀之前調用。
  1. @Component

這個注釋相當于這樣的內容枷踏。<bean name="student" class="com.zts.ioctest.Student" scope="prototype">

  1. @Component注解可以直接定義bean菩暗,而無需在xml定義。但是若兩種定義同時存在旭蠕,xml中的定義會覆蓋類中注解的Bean定義停团。
  2. @Component注解直接寫在類上面即可
  3. @Component有一個可選的參數,用于指定 bean 的名稱:@Component("boss")
  4. @Component容易不指定參數下梢,則 bean 的名稱為當前類的類名小寫
  5. @Component使用之后需要在xml文件配置一個標簽: <context:component-scan/>
  6. <context:component-scan base-package="com.briup.ioc.annotation" /> 可以表示spring需要檢查哪個包下的java類,看它們是否使用了 @Component注解
  7. @Component定義的bean默認情況下都是單例模式的,如果要讓這個bean變?yōu)榉菃卫?可以再結合這個 @Scope 注解來達到目標 @Scope("prototype")

@Component是Spring中所有bean組件的通用形式, @Repository @Service @Controller 則是 @Component的細化,用來表示更具體的用例客蹋,分別對應了持久化層、服務層和表現層孽江。但是至少到現在為止這個四種注解的實質區(qū)別很小(甚至幾乎沒有),都是把當前類注冊為spring容器中的一個bean

注意:
component-scan標簽默認情況下自動掃描指定路徑下的包(含所有子包)讶坯,將帶有 @Component @Repository @Service @Controller標簽的類自動注冊到spring容器。
對標記了 Spring中的 @Required @Autowired @PostConstruct @PreDestroy @Resource @WebServiceRef @EJB @PersistenceContext @PersistenceUnit等注解的類進行對應的操作使注解生效(包含了annotation-config標簽的作用)岗屏。

Spring框架的學習第一天
Spring框架的學習第三天

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末辆琅,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子这刷,更是在濱河造成了極大的恐慌婉烟,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件暇屋,死亡現場離奇詭異似袁,居然都是意外死亡,警方通過查閱死者的電腦和手機咐刨,發(fā)現死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門昙衅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人定鸟,你說我怎么就攤上這事而涉。” “怎么了联予?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵啼县,是天一觀的道長。 經常有香客問我沸久,道長季眷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任卷胯,我火速辦了婚禮瘟裸,結果婚禮上,老公的妹妹穿的比我還像新娘诵竭。我一直安慰自己话告,他們只是感情好,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布卵慰。 她就那樣靜靜地躺著沙郭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪裳朋。 梳的紋絲不亂的頭發(fā)上病线,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音鲤嫡,去河邊找鬼送挑。 笑死,一個胖子當著我的面吹牛暖眼,可吹牛的內容都是我干的惕耕。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼诫肠,長吁一口氣:“原來是場噩夢啊……” “哼司澎!你這毒婦竟也來了?” 一聲冷哼從身側響起栋豫,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤挤安,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后丧鸯,有當地人在樹林里發(fā)現了一具尸體蛤铜,經...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年丛肢,在試婚紗的時候發(fā)現自己被綠了围肥。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡摔踱,死狀恐怖虐先,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情派敷,我是刑警寧澤蛹批,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站篮愉,受9級特大地震影響腐芍,放射性物質發(fā)生泄漏。R本人自食惡果不足惜试躏,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一猪勇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧颠蕴,春花似錦泣刹、人聲如沸助析。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽外冀。三九已至,卻和暖如春掀泳,著一層夾襖步出監(jiān)牢的瞬間雪隧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工员舵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留脑沿,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓马僻,卻偏偏與公主長得像庄拇,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子巫玻,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內容