Spring的IOC

一伦意、入門案例

1.導(dǎo)入依賴:

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

2.編寫beans.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 標(biāo)簽:用于配置讓 spring 創(chuàng)建對(duì)象厨诸,并且存入 ioc 容器之中
    id 屬性:對(duì)象的唯一標(biāo)識(shí)飒赃。
    class 屬性:指定要?jiǎng)?chuàng)建對(duì)象的全限定類名
    -->
    <!-- 配置 service -->
    <bean id="userService" class="com.hcx.service.impl.UserSerivceImpl"></bean>
    <!-- 配置 dao -->
    <bean id="userDao" class="com.hcx.dao.impl.UserDaoImpl"></bean>
</beans>

3.使用

public class UserController {

    public static void main(String[] args) {
        //獲取核心容器
        //ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");//更常用
        ApplicationContext applicationContext = new FileSystemXmlApplicationContext("D:\\config\\beans.xml");
        //根據(jù)id獲取Bean對(duì)象
        //方式一
        UserService userService = (UserService) applicationContext.getBean("userService");
        //方式二
        UserDao userDao = applicationContext.getBean("userDao", UserDao.class);
        //com.hcx.service.impl.UserSerivceImpl@3e6fa38a
        System.out.println(userService);
        //com.hcx.dao.impl.UserDaoImpl@66a3ffec
        System.out.println(userDao);
//        UserService userService = (UserService) BeanFactory.getBean("userService");
//        userService.saveUser();
    }
}

二、重要類詳解

1.BeanFactory

在構(gòu)建核心容器時(shí)聪全,創(chuàng)建對(duì)象采取的策略是延遲加載泊藕。即根據(jù)id獲取對(duì)象時(shí)才創(chuàng)建對(duì)象。
適用場(chǎng)景:多例對(duì)象

public class UserController {
    public static void main(String[] args) {
        Resource resource = new ClassPathResource("beans.xml");
        BeanFactory beanFactory = new XmlBeanFactory(resource);
        UserService userService = (UserService) beanFactory.getBean("userService");
        System.out.println(userService);
    }
}
image.png

2.ApplicationContext

在構(gòu)建核心容器時(shí)难礼,創(chuàng)建對(duì)象采取的是立即加載的方式娃圆。即一讀取完配置文件就馬上創(chuàng)建對(duì)象。
適用場(chǎng)景:?jiǎn)卫龑?duì)象

public class UserController {
    public static void main(String[] args) {
        //獲取核心容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
//        ApplicationContext applicationContext = new FileSystemXmlApplicationContext("D:\\config\\beans.xml");
        //根據(jù)id獲取Bean對(duì)象
        //方式一
        UserService userService = (UserService) applicationContext.getBean("userService");
        //方式二
        UserDao userDao = applicationContext.getBean("userDao", UserDao.class);
        //com.hcx.service.impl.UserSerivceImpl@3e6fa38a
        System.out.println(userService);
        //com.hcx.dao.impl.UserDaoImpl@66a3ffec
        System.out.println(userDao);
    }
}
image.png
image.png

ApplicationContext的三個(gè)常用實(shí)現(xiàn)類:
①ClassPathXmlApplicationContext
可以加載類路徑下的配置文件蛾茉,要求配置文件必須在類路徑下讼呢,否則無(wú)法加載。

②FileSystemXmlApplicationContext
可以加載磁盤任意路徑下的配置文件(須有訪問權(quán)限)

③AnnotationConfigApplicationContext
用于讀取注解創(chuàng)建的容器

三谦炬、Bean詳解

1.創(chuàng)建Bean對(duì)象的三種方式

①方式一:采用默認(rèn)構(gòu)造函數(shù)
<bean id="userService" class="com.hcx.service.impl.UserSerivceImpl"></bean>
spring配置文件中使用bean標(biāo)簽悦屏,僅配置id和class屬性(沒有其他屬性和標(biāo)簽),此時(shí)采用默認(rèn)構(gòu)造函數(shù)創(chuàng)建對(duì)象键思,如果類中沒有默認(rèn)構(gòu)造函數(shù)础爬,則對(duì)象無(wú)法創(chuàng)建。

    <!-- 
        bean 標(biāo)簽:用于配置讓 spring 創(chuàng)建對(duì)象吼鳞,并且存入 ioc 容器之中
        id 屬性:對(duì)象的唯一標(biāo)識(shí)看蚜。
        class 屬性:指定要?jiǎng)?chuàng)建對(duì)象的全限定類名
    -->
    <!-- 配置 service -->
    <bean id="userService" class="com.hcx.service.impl.UserSerivceImpl"></bean>

②方式二:使用普通工廠中的方法創(chuàng)建對(duì)象
即使用某個(gè)類中的方法創(chuàng)建對(duì)象,并存入spring容器
當(dāng)使用一些外部類時(shí)赔桌,如引入的jar中的類供炎,都是字節(jié)碼文件。

InstanceFactory:

/**
 * 模擬工廠類(該類可能存在于jar包中纬乍,無(wú)法修改代碼提供默認(rèn)構(gòu)造函數(shù))
 */
public class InstanceFactory {
    public UserService getUserService(){
        return new UserSerivceImpl();
    }
}

此時(shí)要獲取的是InstanceFactory 類中的getUserService返回值

    <!--得到工廠實(shí)例-->
    <bean id="instanceFactory" class="com.hcx.factory.InstanceFactory"></bean>
    <!--
        factory-bean:指定工廠bean
        factory-method:獲取對(duì)象的方法名
        userService對(duì)象由instanceFactory id所指向的工廠中的getUserService方法獲取
    -->
    <bean id="userService" factory-bean="instanceFactory" factory-method="getUserService"></bean>

③方式三:使用工廠中的靜態(tài)方法創(chuàng)建對(duì)象
使用某個(gè)類中的靜態(tài)方法,并存入spring容器

StaticFactory:

public class StaticFactory {
    public static UserService getUserService(){
        return new UserSerivceImpl();
    }
}

xml配置:

<bean id="userService" class="com.hcx.factory.StaticFactory" factory-method="getUserService"></bean>

④注解方式:
作用和xml配置的<bean>標(biāo)簽功能一樣
@Component:把當(dāng)前類對(duì)象存入spring容器中
屬性value用于指定bean的id裸卫,不寫時(shí)默認(rèn)為類名首字母小寫
@Controller:一般用于表現(xiàn)層
@Service:一般用于業(yè)務(wù)層
@Repository:一般用于持久層

使用注解的方式仿贬,需要加入context命名空間,并且要配置告訴spring使用注解的方式墓贿,需要spring去掃描對(duì)應(yīng)的包茧泪,配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 告知 spring 創(chuàng)建容器時(shí)要掃描的包 -->
    <context:component-scan base-package="com.hcx"></context:component-scan>

</beans>
image.png

2.bean對(duì)象的作用范圍

①xml配置:
默認(rèn)情況spring創(chuàng)建的bean都是單例的。
bean的作用范圍通過bean標(biāo)簽的scope屬性可以指定:
取值:

  • singleton:?jiǎn)卫J(rèn)值)
  • prototype:多例
  • request:作用于web應(yīng)用的請(qǐng)求范圍
  • session:作用于web應(yīng)用的會(huì)話范圍
  • global-session:作用于集群環(huán)境的會(huì)話范圍(全局會(huì)話范圍)聋袋,當(dāng)不是集群環(huán)境時(shí)队伟,等同于session
<bean id="userService" class="com.hcx.service.impl.UserSerivceImpl" scope="singleton"></bean>

②注解配置:
@Scope:指定bean的作用范圍
屬性value:指定范圍的取值,常用取值:singleton幽勒、prototype

3.bean對(duì)象的生命周期

①單例對(duì)象
生命周期跟容器的相同嗜侮,讓其創(chuàng)建時(shí)對(duì)象創(chuàng)建,只要容器還在,對(duì)象一直存活锈颗,容器銷毀顷霹,對(duì)象死亡。
通過init-methoddestory-method屬性指定
UserSerivceImpl:

public class UserSerivceImpl implements UserService {
    public UserSerivceImpl() {
        System.out.println("對(duì)象創(chuàng)建了");
    }
    public void saveUser() {
        System.out.println("service實(shí)現(xiàn)類被調(diào)用了");
//        userDao.saveUser();
    }
    public void init() {
        System.out.println("對(duì)象初始化");
    }
    public void destory() {
        System.out.println("對(duì)象銷毀");
    }
}

xml:

    <bean id="userService" class="com.hcx.service.impl.UserSerivceImpl" scope="singleton"
          init-method="init" destroy-method="destory"></bean>

調(diào)用:

public class UserController {
    public static void main(String[] args) {
        //獲取核心容器
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        //根據(jù)id獲取Bean對(duì)象
        //方式一
        UserService userService = (UserService) applicationContext.getBean("userService");
        //方式二
//        UserDao userDao = applicationContext.getBean("userDao", UserDao.class);
        userService.saveUser();
        //手動(dòng)關(guān)閉容器
        applicationContext.close();
    }
}

結(jié)果:

對(duì)象創(chuàng)建了
對(duì)象初始化
service實(shí)現(xiàn)類被調(diào)用了
對(duì)象銷毀

②多例對(duì)象
出生:使用對(duì)象時(shí)spring框架創(chuàng)建
存活:對(duì)象只要在使用則一直存活
死亡:當(dāng)對(duì)象長(zhǎng)時(shí)間不用且沒有其他對(duì)象引用時(shí)击吱,由垃圾回收器回收

即使手動(dòng)關(guān)閉容器淋淀,對(duì)象也不會(huì)銷毀

    <bean id="userService" class="com.hcx.service.impl.UserSerivceImpl" scope="prototype"
          init-method="init" destroy-method="destory"></bean>

打印結(jié)果:

對(duì)象創(chuàng)建了
對(duì)象初始化
service實(shí)現(xiàn)類被調(diào)用了

③使用注解指定生命周期
作用與bean標(biāo)簽中使用init-methoddestroy-method作用相同
PostConstruct:用于指定初始化方法
PreDestroy:用于指定銷毀方法

UserSerivceImpl :

@Service("userService")
public class UserSerivceImpl implements UserService {
    @Resource(name = "userDao1")
    private UserDao userDao;
    @PostConstruct
    public void init(){
        System.out.println("初始化方法");
    }
    @PreDestroy
    public void destroy(){
        System.out.println("銷毀方法");
    }
    public void saveUser() {
        userDao.saveUser();
    }
}

調(diào)用:

public class UserController {
    @Autowired
    private UserService userService;
    public static void main(String[] args) {
        //獲取核心容器
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        //根據(jù)id獲取Bean對(duì)象
        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.saveUser();
        //手動(dòng)關(guān)閉才會(huì)調(diào)用銷毀方法
        applicationContext.close();
    }
}

打印結(jié)果:

初始化方法
保存用戶1
銷毀方法

四、Spring的依賴注入

依賴注入:Dependency Injection覆醇。它是 spring 框架核心 ioc 的具體實(shí)現(xiàn)
程序在編寫時(shí)朵纷,通過控制反轉(zhuǎn),把對(duì)象的創(chuàng)建交給了 spring永脓,但是代碼中不可能出現(xiàn)沒有依賴的情況袍辞。
ioc 解耦只是降低他們的依賴關(guān)系,但不會(huì)消除憨奸。
例如:我們的業(yè)務(wù)層仍會(huì)調(diào)用持久層的方法革屠。
這種業(yè)務(wù)層和持久層的依賴關(guān)系,在使用 spring 之后排宰,就讓 spring 來(lái)維護(hù)了似芝。
簡(jiǎn)單的說(shuō),就是框架把持久層對(duì)象傳入業(yè)務(wù)層板甘,而不用我們自己去獲取党瓮。

依賴關(guān)系的管理:交由spring來(lái)維護(hù)
當(dāng)前類需要用到其他類對(duì)象時(shí),由spring為我們提供盐类,我們只需要在配置文件中說(shuō)明寞奸。

能注入的數(shù)據(jù)類型:

  • 基本類型和String
  • 其他bean類型(在配置文件或者注解配置過的bean)
  • 復(fù)雜類型(集合類型)

注入的方式:

  • 使用構(gòu)造器
  • 使用set方法
  • 使用注解

注意:經(jīng)常變化的一些數(shù)據(jù)不適用于注入的方式

1.構(gòu)造函數(shù)注入

在bean標(biāo)簽中使用標(biāo)簽constructor-arg,屬性:

  • type:指定要注入的數(shù)據(jù)的數(shù)據(jù)類型在跳,該數(shù)據(jù)類型是構(gòu)造函數(shù)中某個(gè)或某些參數(shù)的數(shù)據(jù)類型
  • index:指定給構(gòu)造函數(shù)中指定索引位置的參數(shù)賦值枪萄。(索引從0開始)
  • name:指定給構(gòu)造函數(shù)中指定名稱的參數(shù)賦值
  • value:賦的值是基本數(shù)據(jù)類型和 String 類型
  • ref:賦的值是其他 bean 類型(必須是在配置文件中配置過的 bean)

注意:typeindex猫妙、name用于指定給構(gòu)造函數(shù)中的哪個(gè)參數(shù)賦值

UserSerivceImpl:

public class UserSerivceImpl implements UserService {
    private String name;
    private Integer age;
    private Date birthday;
    public UserSerivceImpl(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }
    public void saveUser() {
        System.out.println("service實(shí)現(xiàn)類被調(diào)用了:"+name+","+age+","+birthday);
    }
}

beans.xml

    <bean id="userService" class="com.hcx.service.impl.UserSerivceImpl">
        <constructor-arg name="name" value="極多人小紅"></constructor-arg>
        <constructor-arg name="age" value="24"></constructor-arg>
        <constructor-arg name="birthday" ref="date"></constructor-arg>
    </bean>

    <!--配置日期對(duì)象-->
    <bean id="date" class="java.util.Date"></bean>

使用:

public class UserController {

    public static void main(String[] args) {
        //獲取核心容器
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        //根據(jù)id獲取Bean對(duì)象
        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.saveUser();
    }
}

結(jié)果:

service實(shí)現(xiàn)類被調(diào)用了:極多人小紅,24,Wed Dec 11 20:09:09 CST 2019

此種方式的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):在獲取bean對(duì)象時(shí)瓷翻,注入數(shù)據(jù)是必須的操作,否則無(wú)法創(chuàng)建對(duì)象(如果同時(shí)提供無(wú)參構(gòu)造器則沒問題)
缺點(diǎn):改變了bean對(duì)象的實(shí)例化方式割坠,使得在創(chuàng)建對(duì)象時(shí)齐帚,即使不使用這些數(shù)據(jù)也必須提供。

2.set 方法注入

通過配置文件給 bean 中的屬性傳值:使用 set 方法的方式彼哼,
property標(biāo)簽:

  • name:找的是類中 set 方法后面的部分(并不是屬性的名稱)
  • ref:給屬性賦值是其他 bean 類型的
  • value:給屬性賦值是基本數(shù)據(jù)類型和 string 類型的

UserSerivceImpl:

 public class UserSerivceImpl implements UserService {
    private String name;
    private Integer age;
    private Date birthday;
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public void saveUser() {
        System.out.println("service實(shí)現(xiàn)類被調(diào)用了:"+name+","+age+","+birthday);
    }
}

beans.xml:

    <!-- 配置 service -->
    <bean id="userService" class="com.hcx.service.impl.UserSerivceImpl">
        <property name="name" value="極多人小紅"></property>
        <property name="age" value="21"></property>
        <property name="birthday" ref="date"></property>
    </bean>

    <!--配置日期對(duì)象-->
    <bean id="date" class="java.util.Date"></bean>

優(yōu)點(diǎn):創(chuàng)建對(duì)象時(shí)沒有明確的限制对妄,可以直接使用默認(rèn)構(gòu)造函數(shù)
缺點(diǎn):如果某個(gè)成員必須有值,則獲取對(duì)象時(shí)有可能set方法沒有執(zhí)行敢朱。

復(fù)雜類型注入

用于給List結(jié)構(gòu)注入的標(biāo)簽包括:list剪菱、array摩瞎、set
用于給Map結(jié)構(gòu)集合注入的標(biāo)簽包括:mapproperties
即結(jié)構(gòu)相同的數(shù)據(jù)類型琅豆,標(biāo)簽都通用愉豺。

UserSerivceImpl:

public class UserSerivceImpl implements UserService {
    private String[] strArrs;
    private List<String> strList;
    private Set<String> strSet;
    private Map<String,String> strMap;
    private Properties properties;
    public void setStrArrs(String[] strArrs) {
        this.strArrs = strArrs;
    }
    public void setStrList(List<String> strList) {
        this.strList = strList;
    }
    public void setStrSet(Set<String> strSet) {
        this.strSet = strSet;
    }
    public void setStrMap(Map<String, String> strMap) {
        this.strMap = strMap;
    }
    public void setProperties(Properties properties) {
        this.properties = properties;
    }
    public void saveUser() {
        System.out.println("service實(shí)現(xiàn)類被調(diào)用了");
        System.out.println(Arrays.toString(strArrs));
        System.out.println(strList);
        System.out.println(strSet);
        System.out.println(strMap);
        System.out.println(properties);
    }
}

beans.xml:

<bean id="userService" class="com.hcx.service.impl.UserSerivceImpl">
        <property name="strArrs">
            <array>
                <value>arr1</value>
                <value>arr2</value>
                <value>arr3</value>
            </array>
        </property>

        <property name="strList">
            <list>
                <value>list1</value>
                <value>list2</value>
                <value>list3</value>
            </list>
        </property>

        <property name="strSet">
            <set>
                <value>set1</value>
                <value>set2</value>
                <value>set3</value>
            </set>
        </property>

        <property name="strMap">
            <map>
                <entry key="keya" value="map1"></entry>
                <entry key="keyb">
                    <value>map2</value>
                </entry>
            </map>
        </property>

        <property name="properties">
            <props>
                <prop key="propertieskey1">properties1</prop>
                <prop key="propertieskey2">properties2</prop>
            </props>
        </property>
    </bean>

調(diào)用:

public class UserController {

    public static void main(String[] args) {
        //獲取核心容器
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        //根據(jù)id獲取Bean對(duì)象
        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.saveUser();
    }
}

打印結(jié)果:


image.png

3.注解注入

@Autowired:按照類型注入
只要容器中有唯一的一個(gè)bean對(duì)象類型和要注入的變量類型匹配,就能注入成功茫因。
如果容器中沒有bean的類型和要注入的變量匹配蚪拦,報(bào)錯(cuò)。
如果容器中有多個(gè)類型匹配時(shí)冻押,報(bào)錯(cuò)驰贷。

image.png

注意:當(dāng)有多個(gè)類型都匹配上時(shí),會(huì)再次按照名稱匹配洛巢,如果相同了括袒,也能匹配上。
即注入時(shí)的類的名稱private UserDao userDao2;userDao2與聲明時(shí)的注解@Repository("userDao2")匹配上了稿茉。

@Qualifier:按照類型注入的基礎(chǔ)之上再按照名稱注入锹锰。
(給方法參數(shù)注入時(shí)可以單獨(dú)使用,給類成員注入時(shí)則不能單獨(dú)使用漓库,必須配合@Autowired注解)
value屬性:用于指定注入bean的id

@Service("userService")
public class UserSerivceImpl implements UserService {
    @Autowired
    @Qualifier("userDao1")
    private UserDao userDao;
    public void saveUser() {
        userDao.saveUser();
    }
}

@Resource:按照bean的id注入恃慧,可以單獨(dú)使用
屬性name:用于指定bean的id

@Service("userService")
public class UserSerivceImpl implements UserService {
//    @Autowired
//    @Qualifier("userDao1")
    @Resource(name = "userDao1")
    private UserDao userDao;
    public void saveUser() {
        userDao.saveUser();
    }
}

總結(jié):以上三個(gè)注解只能注入bean類型的數(shù)據(jù)。

@Value:用于注入基本類型和String類型數(shù)據(jù)
屬性value:指定數(shù)據(jù)的值渺蒿,可以使用SpEL(spring的el表達(dá)式)
SpEL寫法:${表達(dá)式}

位置:變量痢士、方法

五、使用純注解的方式配置(沒有beans.xml配置文件)

beans.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 告知 spring 創(chuàng)建容器時(shí)要掃描的包 -->
    <context:component-scan base-package="com.hcx"></context:component-scan>

    <bean id="runner" class="org.apache.commons.dbutils.QueryRunner"  scope="prototype">
        <constructor-arg name="ds" ref="dataSource"></constructor-arg>
    </bean>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/springdemo"></property>
        <property name="user" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
</beans>

@Configuration:指定當(dāng)前類是一個(gè)配置類
當(dāng)配置類作為AnnotationConfigApplicationContext對(duì)象創(chuàng)建的參數(shù)傳遞時(shí)茂装,可以省略該注解怠蹂。
@ComponentScan(basePackage="com.hcx"):指定spring在創(chuàng)建容器時(shí)需要掃描的包
屬性value和basePackages:作用相同,都是用于指定創(chuàng)建容器時(shí)需要掃描的包少态。
使用此注解就相當(dāng)于在xml中配置了:<context:component-scan base-package="com.hcx"></context:component-scan>
@Bean用于把當(dāng)前方法的返回值作為bean對(duì)象存入spring的ioc容器中
屬性name:指定bean的id城侧,默認(rèn)值為當(dāng)前方法名
@import:導(dǎo)入其他配置類
屬性value:用于指定其他配置類的字節(jié)碼(使用了該注解的類就是主配置類)
@PropertySource:用于指定配置文件的路徑
屬性value:指定文件名稱和路徑(classpath:類路徑)

image.png

SpringConfiguration:

@Configuration
@ComponentScan("com.hcx")
public class SpringConfiguration {

    @Bean(name = "runner")
    @Scope("prototype")
    public QueryRunner createQueryRunner(DataSource dataSource) {
        return new QueryRunner(dataSource);
    }

    @Bean(name = "dataSource")
    public DataSource createDataSource() {
        try {
            ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
            comboPooledDataSource.setDriverClass("com.mysql.jdbc.Driver");
            comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/springdemo");
            comboPooledDataSource.setUser("root");
            comboPooledDataSource.setPassword("root");
            return comboPooledDataSource;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

測(cè)試:

public class UserServiceTest {
    @Test
    public void testSelectAll(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
        UserService userService = applicationContext.getBean("userService", UserService.class);
        List<User> userList = userService.findAll();
        for(User user : userList){
            System.out.println(user);
        }
    }
}

注意:使用注解配置,方法如果有參數(shù)彼妻,spring會(huì)尋找有沒有對(duì)應(yīng)的bean對(duì)象嫌佑,查找方式與Autowired一樣。

@import注解

當(dāng)有多個(gè)配置類時(shí)澳骤,可以通過@import注解導(dǎo)入其他的配置類
主配置類:

@ComponentScan("com.hcx")
@Import(JdbcConfig.class)
public class SpringConfiguration {
}

Jdbc配置類:

public class JdbcConfig {

    @Bean(name = "runner")
    @Scope("prototype")
    public QueryRunner createQueryRunner(DataSource dataSource) {
        return new QueryRunner(dataSource);
    }

    @Bean(name = "dataSource")
    public DataSource createDataSource() {
        try {
            ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
            comboPooledDataSource.setDriverClass("com.mysql.jdbc.Driver");
            comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/springdemo");
            comboPooledDataSource.setUser("root");
            comboPooledDataSource.setPassword("root");
            return comboPooledDataSource;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

@PropertySource注解

使用讀取配置文件的方式讀取數(shù)據(jù)庫(kù)配置信息:
將數(shù)據(jù)庫(kù)的配置抽取到單獨(dú)的properties文件中:
jdbcConfig.properties:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springdemo
jdbc.useranme=root
jdbc.password=root

JdbcConfig:

public class JdbcConfig {

    @Value("${jdbc.driver}")
    private String driver;

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    @Bean(name = "runner")
    @Scope("prototype")
    public QueryRunner createQueryRunner(DataSource dataSource) {
        return new QueryRunner(dataSource);
    }

    @Bean(name = "dataSource")
    public DataSource createDataSource() {
        try {
            ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
            comboPooledDataSource.setDriverClass(driver);
            comboPooledDataSource.setJdbcUrl(url);
            comboPooledDataSource.setUser(username);
            comboPooledDataSource.setPassword(password);
            return comboPooledDataSource;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

在配置類中指定讀取該配置:
SpringConfiguration:

@ComponentScan("com.hcx")
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {
}

在方法參數(shù)上使用@Qualifier注解

當(dāng)有多個(gè)數(shù)據(jù)源時(shí)歧强,可以在創(chuàng)建對(duì)象時(shí)通過@Qualifier注解參數(shù)指定具體使用哪一個(gè):

image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末澜薄,一起剝皮案震驚了整個(gè)濱河市为肮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌肤京,老刑警劉巖颊艳,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茅特,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡棋枕,警方通過查閱死者的電腦和手機(jī)白修,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)重斑,“玉大人兵睛,你說(shuō)我怎么就攤上這事】耍” “怎么了祖很?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)漾脂。 經(jīng)常有香客問我假颇,道長(zhǎng),這世上最難降的妖魔是什么骨稿? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任笨鸡,我火速辦了婚禮,結(jié)果婚禮上坦冠,老公的妹妹穿的比我還像新娘形耗。我一直安慰自己,他們只是感情好蓝牲,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布趟脂。 她就那樣靜靜地躺著,像睡著了一般例衍。 火紅的嫁衣襯著肌膚如雪昔期。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天佛玄,我揣著相機(jī)與錄音硼一,去河邊找鬼。 笑死梦抢,一個(gè)胖子當(dāng)著我的面吹牛般贼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播奥吩,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼哼蛆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了霞赫?” 一聲冷哼從身側(cè)響起腮介,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎端衰,沒想到半個(gè)月后叠洗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體甘改,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年灭抑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了十艾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡腾节,死狀恐怖忘嫉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情案腺,我是刑警寧澤榄融,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站救湖,受9級(jí)特大地震影響愧杯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鞋既,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一力九、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧邑闺,春花似錦跌前、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至靶衍,卻和暖如春灾炭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背颅眶。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工蜈出, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人涛酗。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓铡原,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親商叹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子燕刻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容