日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

小白新手web開發(fā)簡(jiǎn)單總結(jié)(六)-Spring的IoC容器

 印度阿三17 2021-02-19

目錄

一 前言

二 什么是IoC容器

三 實(shí)例

1.通過XML配置規(guī)則

2.通過注解

3.Spring中的其他幾種注解

四 JavaBean生命周期的監(jiān)聽

五 總結(jié)


一 前言

接上篇小白新手web開發(fā)簡(jiǎn)單總結(jié)(四)-web應(yīng)用開發(fā)中的MVC總結(jié)下IoC容器的相關(guān)內(nèi)容。

IoC容器是Spring框架的一個(gè)核心功能。通過該容器來管理所有的JavaBean組件,提供組件的生命周期管理、配置和組裝、AOP支持、以及建立在AOP基礎(chǔ)上的聲明事務(wù)服務(wù)等。

二 什么是IoC容器

IoC(Inversion of Control 控制反轉(zhuǎn))容器

通常Java組件通過new一個(gè)實(shí)例的方式實(shí)現(xiàn)組件之間的引用,并且組件中的兩個(gè)實(shí)例都含有共享組件的時(shí)候,也不能共享該組件。如果系統(tǒng)中有大量的組件的時(shí)候,不僅要維護(hù)組件的生命周期,還要維護(hù)組件之間的依賴關(guān)系,大大增加了系統(tǒng)的復(fù)雜度,而且組件之間會(huì)相互耦合,這些控制流程完全有開發(fā)者自行控制。

而IoC容器就是將控制權(quán)進(jìn)行反轉(zhuǎn),將控制權(quán)交給了IoC容器,由IoC容器負(fù)責(zé)組件的創(chuàng)建和配置,負(fù)責(zé)組件的生命周期管理,而開發(fā)者只需要定義裝配規(guī)則,這樣就將組件的創(chuàng)建配置和組件的使用進(jìn)行分離。并且如果在一個(gè)組件的多個(gè)實(shí)例中含有共享組件的時(shí)候,是可以相互共享的,不需要多次注入。

在Spring的IoC容器中,所有的組件都被成為JavaBean組件,每個(gè)組件即一個(gè)Bean。

通常有兩種方式來定義組件的配置規(guī)則:

  • (1)XML
  • (2)注解

三 實(shí)例

通過一個(gè)簡(jiǎn)單的實(shí)例來看下這個(gè)JavaBean組件是怎么定義配置規(guī)則。

1.通過XML配置規(guī)則

  • 1.在項(xiàng)目pom.xml中引入spring-context依賴
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
  • 2.定義項(xiàng)目中需要使用的JavaBean

(1)定義一個(gè)RegisterService:通過輸入的手機(jī)號(hào)碼和密碼,來注冊(cè)該用戶,并將注冊(cè)成功之后給用戶發(fā)送注冊(cè)成功的短信。

public class RegisterService {
    private MessageService messageService;

    public void setMessageService(MessageService service) {
        this.messageService = service;
    }

    public User register(String phone, String password) {
        User user = new User();
        user.phone = phone;
        user.password = password;
        //隨機(jī)生成一個(gè)用戶名
        user.name = "小劉";
        //需要將該信息寫入數(shù)據(jù)庫(kù)
        SqlDataBase sql = new SqlDataBase();
        sql.insert(user);
        //注冊(cè)成功之后,給用戶發(fā)送短息
        if (messageService == null) {
            System.err.println("還沒有初始化MessageService");
            return user;
        }
        messageService.sendRegisterSuccessMessage(phone);
        return user;

    }

}

(2)定義MessageService:?向用戶的手機(jī)發(fā)送短信(邏輯省略)

public class MessageService {
    /**
     * 發(fā)送短信
     *
     * @param phone
     */
    public void sendRegisterSuccessMessage(String phone) {
        String message = "您已經(jīng)成功注冊(cè)該網(wǎng)站賬戶";
        System.out.println(String.format("已經(jīng)成功的向%s發(fā)送注冊(cè)短信:%s", phone, message));
    }
}
  • 3.定義配置JavaBean的規(guī)則

(1)在resouce目錄下添加application-context.xml的文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www./schema/beans"
       xmlns:xsi="http://www./2001/XMLSchema-instance"
       xsi:schemaLocation="http://www./schema/beans
        https://www./schema/beans/spring-beans.xsd">

    <bean id="registerService" class="com.wj.spring.RegisterService">
        <property name="messageService" ref="messageService"/>
    </bean>

    <bean id="messageService" class="com.wj.spring.MessageService">
    </bean>
</beans>

其中id為該bean的唯一識(shí)別 ,通過?<property name="messageService" ref="messageService"/>的方式在RegisterService中增加了MessageService的引用,其實(shí)上面的XML配置的內(nèi)容就等價(jià)于下面的java代碼:

    MessageService messageService = new MessageService();
    RegisterService registerService = new RegisterService();
    registerService.setMessageService(messageService);
  • 4.通過讀取XML文件,獲取到ApplicationContext,也就是IoC容器
public class RegisterApplication {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("config/application-context.xml");
        RegisterService service = context.getBean(RegisterService.class);
        //RegisterService service = (RegisterService)context.getBean("registerService");
        User user = service.register("12345678901", "123456");
        System.out.println("注冊(cè)之后的用戶名為:"   user.name);      
    }
}

當(dāng)?ClassPathXmlApplicationContext要傳入的是這個(gè)application-context.xml的相對(duì)路徑。這樣就可以context.getBean()的方式獲取到定義的JavaBean。運(yùn)行項(xiàng)目如下:

相關(guān)的代碼已經(jīng)上傳到github:https://github.com/wenjing-bonnie/build-spring.git:對(duì)應(yīng)的com/wj/spring下的相關(guān)代碼。

2.通過注解

使用XML文件的方式,可以把所有的JavaBean的都一一列舉出來,并且通過配置注入能直觀的了解到每個(gè)JavaBean的依賴關(guān)系,但是缺點(diǎn)也就顯現(xiàn)出來,這種寫法非常繁瑣,每增加一個(gè)組件,就必須在XML將該組件添加進(jìn)去。所以就有了注解這種方式,可以讓IoC容器自動(dòng)掃描所有的Bean并組裝他們。

  • 1.同上面的1
  • 2.同樣定義同上面的JavaBean,只不過在JavaBean增加@Component注解,來標(biāo)示是一個(gè)JavaBean組件

(1)定義一個(gè)RegisterService

@Component
public class RegisterAnnotationService {
    //   @Autowired將指定類型的Bean直接注入到指定的字段
    @Autowired
    private MessageAnnotationService messageAnnotationService;

}

通過?@Autowired將指定類型的Bean直接注入到指定的字段。當(dāng)然@Autowired也可以注解List<JavaBean>集合中,這樣每增加一個(gè)同類型的JavaBean,都會(huì)被IoC容器自動(dòng)裝配到該集合中。如果要設(shè)置JavaBean被裝配的順序,則可通過在組件上增加@Order(1)、@Order(2)……

默認(rèn)情況下,當(dāng)給定字段標(biāo)記了?@Autowired,如果IoC容器沒有找到對(duì)應(yīng)的JavaBean,則會(huì)拋出NoSuchBeanDefinitionException異常,所以可以增加@Autowired(required=false)來避免該異常。

(2)定義MessageService

@Component
public class MessageAnnotationService {

}

通過增加上面的兩個(gè)注解的方式,就完成了JavaBean之間的配置規(guī)則。

默認(rèn)的將JavaBean標(biāo)記為@Component,那么IoC容器會(huì)自動(dòng)創(chuàng)建一個(gè)單例,即容器初始化的時(shí)候創(chuàng)建JavaBean,容器銷毀的時(shí)候銷毀。在整個(gè)容器運(yùn)行期間,getBean()獲取的是一個(gè)實(shí)例。

其實(shí)可以通過@Scope來標(biāo)記該實(shí)例的作用域:即@Scope(value = "singleton")或@Scope( "singleton"),該value對(duì)應(yīng)的有四種作用域

singleton :唯一的bean實(shí)例,默認(rèn)的為單例。即getBean()獲取的是一個(gè)實(shí)例。

prototype:每次容器返回的都是一個(gè)新的實(shí)例。即getBean()獲取的都是一個(gè)新的實(shí)例。

request:每次Http請(qǐng)求的時(shí)候都會(huì)產(chǎn)生一個(gè)新的實(shí)例,僅在當(dāng)前request請(qǐng)求中有效。

session:每次Http請(qǐng)求的時(shí)候都會(huì)產(chǎn)生一個(gè)新的實(shí)例,僅在當(dāng)前session內(nèi)有效。

  • 3.通過讀取注解來獲得到IoC容器
@Configuration  //用來標(biāo)明是一個(gè)配置類,在創(chuàng)建AnnotationConfigApplicationContext,需要傳入該類
@ComponentScan //用來告訴容器,自動(dòng)掃描當(dāng)前類所在的包以及子包,把所有標(biāo)注為@Component的Bean都自動(dòng)創(chuàng)建出來,并根據(jù)@Autowired進(jìn)行裝配
public class RegisterAnnotationApplication {

    public static void main(String[] args) {
       ApplicationContext context = new  AnnotationConfigApplicationContext(RegisterAnnotationApplication.class);
        RegisterAnnotationService service = context.getBean(RegisterAnnotationService.class);
        //RegisterService service = (RegisterService)context.getBean("registerService");
        User user = service.register("12345678901", "123456");
        System.out.println("注冊(cè)之后的用戶名為:"   user.name);
    }
}

不同于通過XML文件的配置方式,在讀取ApplicationContext的時(shí)候,需要將該類增加一個(gè)?@Configuration ?用來標(biāo)明是一個(gè)配置類(其實(shí)@Configuration可以用@Component來代替,也就是如果分不清這個(gè)組件具體什么作用,那就直接用@Component),在創(chuàng)建AnnotationConfigApplicationContext的時(shí)候,需要傳入該類;增加@ComponentScan 用來告訴容器,自動(dòng)掃描當(dāng)前類所在的包以及子包,把所有標(biāo)注為@Component的Bean都自動(dòng)創(chuàng)建出來,并根據(jù)@Autowired進(jìn)行裝配。

運(yùn)行項(xiàng)目結(jié)果和上面的一致。相關(guān)代碼已經(jīng)上傳github:https://github.com/wenjing-bonnie/build-spring.git:對(duì)應(yīng)的com/wj/springannotation下的相關(guān)代碼。

3.Spring中的其他幾種注解

1.JavaBean組件相關(guān)的注解

像之前大體有印象的一些@Controller/@RestController、@Service、@Respository等這些都是用來注解為JavaBean,只不過這是在后面的Spring MVC具有一些特殊功能的JavaBean,如果分不清該組件屬于哪一種,就直接使用@Component來注解。

2.讀取配置文件、資源文件等相關(guān)注解

  • (1)讀取Resources下面的一些普通的文件

使用IoC容器,可以很方便的把這些文件引入進(jìn)來,方便程序讀取,省掉了很多繁瑣的代碼來獲取InputStream。在Maven項(xiàng)目中,經(jīng)常會(huì)將這些文件放置到Resources目錄下,所以Spring框架就提供了org.springframework.core.io.Resource來可以直接讀取到文件的InputStream

    @Value("readme.txt")
    private Resource readmeTxt;

那么在項(xiàng)目中就可以通過readmeTxt.getInputStream()獲取到該txt的inputstream。

  • ?(2)讀取Resouces下的一些key/value結(jié)構(gòu)的文件

經(jīng)常有些配置文件是key/value形式的存在文件中,在使用上面的方式,顯得不太方便,那么IoC容器還提供了更簡(jiǎn)便的方式來讀取。通過添加@PropertySource注解的方式,就可以直接根據(jù)key來獲取到對(duì)應(yīng)的value。例如有一個(gè)配置文件config/application.properties的內(nèi)容如下:

application.ipaddress = 192.168.110.118

我們只需要在需要讀取該配置文件的組件上添加?@PropertySource("config/application.properties"),那么就可以通過key來得到對(duì)應(yīng)的value值。

@Configuration
@PropertySource("config/application.properties")
public class ApplicationConfig {
    @Value("${application.ipaddress}")
    public String ipAddress;
}

?@Value("${application.ipaddress}"):為沒有默認(rèn)值的value,如果想給定默認(rèn)值的話,則?@Value("${application.ipaddress:192.168.0.0}")。

  • (3)在其他組件中引用配置文件的相關(guān)內(nèi)容

還是上面的例子,如果在其他地方也要引用config/application.properties里面的配置項(xiàng),其實(shí)可以直接通過@Value("#{bean.property}")的方式來得到對(duì)應(yīng)的配置項(xiàng),bean就是ApplicationConfig的實(shí)例applicationConfig(該實(shí)例不需要引入,只是組件名的首字母小寫)的ipAddress屬性值引入到OtherAnnotation。

@Component
public class OtherAnnotation {

    @Value("#{applicationConfig.ipAddress}")
    public String ipAddress;
}

通過該注解方式,在OtherAnnotation中可以不用引入config/application.properties就可以讀取到定義在ApplicationConfig里面的配置項(xiàng)。與(2)不同的是,在(2)中使用的是@Value("${key:defaultValue}")的形式讀取配置文件中的值,而在OtherAnnotation中通過@Value("#{bean.property}")讀取在ApplicationConfig中讀到的配置項(xiàng)。

四 JavaBean生命周期的監(jiān)聽

當(dāng)我們將一個(gè)JavaBean添加到IoC容器時(shí),有的時(shí)候可能需要在容器初始化該JavaBean的時(shí)候監(jiān)聽消息等,在容器關(guān)閉的時(shí)候清理資源。那么就可以通過在該JavaBean只能夠定義兩個(gè)方法,在項(xiàng)目中引入javax.annotation依賴,通過javax.annotation的@PostContruct和@PreDestroy添加到上述的兩個(gè)方法中。其過程如下:

(1)在pom.xml添加javax.annotation依賴

        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.2</version>
        </dependency>

(2)在MessageAnnotationService中需要承載初始化和銷毀的方法上添加@PostContruct和@PreDestroy

public class MessageAnnotationService {

    @PostConstruct
    public void init() {
        System.out.println("MessageAnnotationService init");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("MessageAnnotationService destroy");
    }
}

這樣在IoC容器初始化和銷毀的時(shí)候,就會(huì)看到對(duì)應(yīng)的方法的調(diào)用 。

五 總結(jié)

1.Spring的核心功能就是IoC容器,提供組件的創(chuàng)建和裝配,只需要定義配置規(guī)則,IoC容器會(huì)自動(dòng)完成所有的過程;

2.可以通過XML文件和注解兩種方式來定義組件之間的配置規(guī)則;

3.終于搞明白了項(xiàng)目中為什么有那么多bean的配置文件;

4.使用@Component來注解一個(gè)類為組件,那么IoC容器在啟動(dòng)的時(shí)候,就會(huì)自動(dòng)初始化該組件;

5.可以用@Scope來指定組件實(shí)例的作用域,是單例還是每次都是一個(gè)新的實(shí)例;

6.一個(gè)ApplicationContext就是一個(gè)IoC容器,可以從ApplicationContext中通過getBean()來獲取到對(duì)應(yīng)的組件實(shí)例;

7.使用javax.annotation可以在組件初始化或者銷毀的時(shí)候做一些事情;

8.可以使用Resource輕松得到resouces下的文件的inputStream;

9.可以通過?@PropertySource的方式輕松得到配置文件的key/value;

10.之前有點(diǎn)印象的@Controller/@RestController、@Service、@Respository等其實(shí)都是一些組件,只不過是一些擁有特殊功能的組件。

每天都在進(jìn)步一點(diǎn),加油?。?!?

來源:https://www./content-4-862751.html

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多