国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Spring高手之路——深入理解注解驅(qū)動配置與XML配置的融合與區(qū)別

這篇具有很好參考價值的文章主要介紹了Spring高手之路——深入理解注解驅(qū)動配置與XML配置的融合與區(qū)別。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

1. 配置類的編寫與Bean的注冊

??XML配置中,我們通常采用ClassPathXmlApplicationContext,它能夠加載類路徑下的XML配置文件來初始化Spring應用上下文。然而,在注解驅(qū)動的配置中,我們則使用以Annotation開頭和ApplicationContext結(jié)尾的類,如AnnotationConfigApplicationContext。AnnotationConfigApplicationContextSpring容器的一種,它實現(xiàn)了ApplicationContext接口。

??對比于 XML 文件作為驅(qū)動,注解驅(qū)動需要的是配置類。一個配置類就可以類似的理解為一個 XML 。配置類沒有特殊的限制,只需要在類上標注一個 @Configuration 注解即可。

我們創(chuàng)建一個 Book 類:

public class Book {
    private String title;

    private String author;


    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}

xml 中聲明 Bean 是通過 <bean> 標簽

<bean id="book" class="com.example.Book">
    <property name="title" value="Java Programming"/>
    <property name="author" value="Unknown"/>
</bean>

如果要在配置類中替換掉 <bean> 標簽,需要使用 @Bean 注解

我們創(chuàng)建一個配置類來注冊這個 Book bean

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class LibraryConfiguration {
    @Bean
    public Book book() {
        Book book = new Book();
        book.setTitle("Java Programming");
        book.setAuthor("Unknown");
        return book;
    }
}

??在這個配置中,我們使用了 @Configuration 注解來表示這是一個配置類,類似于一個 XML 文件。我們在 book() 方法上使用了 @Bean 注解,這意味著這個方法將返回一個由 Spring 容器管理的對象。這個對象的類型就是 Book,bean 的名稱id就是方法的名稱,也就是 “book”。

??類似于 XML 配置的 <bean> 標簽,@Bean 注解負責注冊一個 bean。你可以把 @Bean 注解看作是 <bean> 標簽的替代品。

??如果你想要更改這個 bean 的名稱,你可以在 @Bean 注解中使用 name 屬性:

   @Bean(name="mybook")
    public Book book() {
        Book book = new Book();
        book.setTitle("Java Programming");
        book.setAuthor("Unknown");
        return book;
    }

??這樣,這個 Book bean 的名稱就變成了 “mybook”。

啟動并初始化注解驅(qū)動的IOC容器

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
		ApplicationContext context = new AnnotationConfigApplicationContext(LibraryConfiguration.class);

        // 從容器中獲取 Book bean
        LibraryConfiguration libraryConfiguration = context.getBean(LibraryConfiguration.class);
        System.out.println(libraryConfiguration.book().getTitle());
        System.out.println(libraryConfiguration.book().getAuthor());
    }
}

??ApplicationContext context = new AnnotationConfigApplicationContext(LibraryConfiguration.class)這個語句創(chuàng)建了一個Spring的應用上下文,它是以配置類LibraryConfiguration.class作為輸入的,這里明確指定配置類的Spring應用上下文,適用于更一般的Spring環(huán)境。

??對比一下ApplicationContext context = SpringApplication.run(DemoApplication.class, args);這個語句則是Spring Boot應用的入口,啟動一個Spring Boot應用。SpringApplication.run()方法會創(chuàng)建一個Spring Boot應用上下文(也就是一個SpringApplication對象),這個上下文包含了Spring Boot應用所有的Bean和配置類,還有大量的默認配置。這個方法之后,Spring Boot的自動配置就會起作用。你可以把SpringApplication.run()創(chuàng)建的Spring Boot上下文看作是更加功能豐富的Spring上下文。

打印結(jié)果:

Spring高手之路——深入理解注解驅(qū)動配置與XML配置的融合與區(qū)別

Java ProgrammingUnknown被打印,執(zhí)行成功。

注意:@SpringBootApplication是一個復合注解,它等效于同時使用了@Configuration,@EnableAutoConfiguration@ComponentScan。這三個注解的作用是:

  • @Configuration:指明該類是一個配置類,它可能會有零個或多個@Bean注解,方法產(chǎn)生的實例由Spring容器管理。

  • @EnableAutoConfiguration:告訴Spring Boot根據(jù)添加的jar依賴自動配置你的Spring應用。

  • @ComponentScanSpring Boot會自動掃描該類所在的包以及子包,查找所有的Spring組件,包括@Configuration類。

??在非Spring Boot的傳統(tǒng)Spring應用中,我們通常使用AnnotationConfigApplicationContext或者ClassPathXmlApplicationContext等來手動創(chuàng)建和初始化SpringIOC容器。

??"非Spring Boot的傳統(tǒng)Spring應用"是指在Spring Boot項目出現(xiàn)之前的Spring項目,這些項目通常需要手動配置很多東西,例如數(shù)據(jù)庫連接、事務管理、MVC控制器等。這種類型的Spring應用通常需要開發(fā)者對Spring框架有深入的了解,才能做出正確的配置。

??Spring BootSpring項目的一個子項目,它旨在簡化Spring應用的創(chuàng)建和配置過程。Spring Boot提供了一系列的"起步依賴",使得開發(fā)者只需要添加少量的依賴就可以快速開始項目的開發(fā)。此外,Spring Boot還提供了自動配置的特性,這使得開發(fā)者無需手動配置數(shù)據(jù)庫連接、事務管理、MVC控制器等,Spring Boot會根據(jù)項目的依賴自動進行配置。

??因此,"非Spring Boot的傳統(tǒng)Spring應用"通常需要手動創(chuàng)建和初始化SpringIOC容器,比如使用AnnotationConfigApplicationContextClassPathXmlApplicationContext等。在Spring Boot應用中,這個過程被自動化了,開發(fā)者只需要在main方法中調(diào)用SpringApplication.run方法,Spring Boot就會自動創(chuàng)建和初始化SpringIOC容器。SpringApplication.run(Application.class, args);語句就是啟動Spring Boot應用的關(guān)鍵。它會啟動一個應用上下文,這個上下文會加載所有的Spring組件,并且也會啟動SpringIOC容器。在這個過程中,所有通過@Bean注解定義的bean都會被創(chuàng)建,并注冊到IOC容器中。

??有人說,那學習Spring Boot就好了,學什么Spring和Spring MVC啊,這不是落后了嗎

??Spring Boot并不是Spring框架的替代品,而是建立在Spring框架之上的一種工具,它內(nèi)部仍然使用Spring框架的很多核心技術(shù),包括Spring MVC。所以,當我們在使用Spring Boot時,我們實際上仍然在使用Spring MVC來處理Web層的事務。

??簡而言之,Spring MVC是一個用于構(gòu)建Web應用程序的框架,而Spring Boot是一個用于簡化Spring應用程序開發(fā)的工具,它內(nèi)部仍然使用了Spring MVC。你在Spring Boot應用程序中使用的@Controller、@Service@Autowired等注解,其實都是Spring框架提供的,所以,原理性的東西還是需要知道。


2. 注解驅(qū)動IOC的依賴注入與XML依賴注入對比

我們就以上面的例子來說,假設配置類注冊了兩個bean,并設置相關(guān)的屬性:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class LibraryConfiguration {
    @Bean
    public Book book() {
        Book book = new Book();
        book.setTitle("Java Programming");
        book.setAuthor("Unknown");
        return book;
    }

    @Bean
    public Library library() {
        Library library = new Library();
        library.setBook(book());
        return library;
    }
}

??這里的方法有@Bean注解,這個注解告訴Spring,這個方法返回的對象需要被注冊到SpringIOC容器中。

如果不用注解,要實現(xiàn)相同功能的話,對應的XML配置如下:

<bean id="book" class="com.example.Book">
    <property name="title" value="Java Programming"/>
    <property name="author" value="Unknown"/>
</bean>

<bean id="library" class="com.example.Library">
    <property name="book" ref="book"/>
</bean>

??在這個XML配置中,我們定義了兩個<bean>元素,分別用來創(chuàng)建Book對象和Library對象。在創(chuàng)建Book對象時,我們使用了<property>元素來設置titleauthor屬性。在創(chuàng)建Library對象時,我們也使用了<property>元素,但是這次我們使用了ref屬性來引用已經(jīng)創(chuàng)建的Book對象,這就相當于將Book對象注入到Library對象中。


3. Spring中組件的概念

??在Spring框架中,當我們說 “組件” 的時候,我們通常指的是被Spring管理的各種Java對象,這些對象在Spring的應用上下文中作為Bean存在。這些組件可能是服務層的類、數(shù)據(jù)訪問層的類、控制器類、配置類等等。

??@ComponentScan注解會掃描指定的包(及其子包)中的類,如果這些類上標注了@Component、@Controller、@Service、@Repository、@Configuration等注解,那么Spring就會為這些類創(chuàng)建Bean定義,并將這些Bean定義注冊到Spring的應用上下文中。因此,我們通常說@ComponentScan進行了"組件掃描",因為它掃描的是標注了上述注解的類,這些類在Spring中都被視為組件。

??而這些注解標記的類,最終在Spring的應用上下文中都會被創(chuàng)建為Bean,因此,你也可以理解@ComponentScan為"Bean掃描"。但是需要注意的是,@ComponentScan只負責掃描和注冊Bean定義,Bean定義就是元數(shù)據(jù)描述,包括了如何創(chuàng)建Bean實例的信息。

總結(jié)一下,@ComponentScan注解會掃描并注冊的"組件"包括:

  • 標注了@Component注解的類
  • 標注了@Controller注解的類(Spring MVC中的控制器組件)
  • 標注了@Service注解的類(服務層組件)
  • 標注了@Repository注解的類(數(shù)據(jù)訪問層組件)
  • 標注了@Configuration注解的類(配置類)

這些組件最終都會在Spring的應用上下文中以Bean的形式存在。


4. 組件注冊

這里Library 標注 @Configuration 注解,即代表該類會被注冊到 IOC 容器中作為一個 Bean。

@Component
public class Library {
}

相當于 xml 中的:

<bean id="library" class="com.example.demo.configuration.Library">

如果想指定 Bean 的名稱,可以直接在 @Configuration 中聲明 value 屬性即可

@Component("libra")
public class Library {
}

??@Component("libra")就將這個bean的名稱改為了libra,如果不指定 Bean 的名稱,它的默認規(guī)則是 “類名的首字母小寫”(例如Library 默認名稱是 library )


5. 組件掃描

如果我們只寫了@Component@Configuration 這樣的注解,IOC容器是找不到這些組件的。

5.1 使用@ComponentScan的組件掃描

忽略掉之前的例子,在這里我們需要運行的代碼如下:

@Component
public class Book {
    
    private String title = "Java Programming";
    private String author = "Unknown";

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}
@Component
public class Library {
    @Resource
    private Book book;

    public Book getBook() {
        return book;
    }

    public void setBook(Book book) {
        this.book = book;
    }
}

如果不寫@ComponentScan,而且@Component注解標識的類不在當前包或者子包,那么就會報錯。

Spring高手之路——深入理解注解驅(qū)動配置與XML配置的融合與區(qū)別

??難道@Component注解標識的類在當前包或者當前包的子包,主程序上就可以不寫@ComponentScan了嗎?

??是的!前面說了,@SpringBootApplication 包含了 @ComponentScan,其實已經(jīng)幫我們寫了!只有組件和主程序不在一個共同的根包下,才需要顯式地使用 @ComponentScan 注解。由于 Spring Boot 的設計原則是“約定優(yōu)于配置”,所以推薦將主應用類放在根包下。

??在應用中,我們的組件(帶有 @Component、@Service、@Repository@Controller 等注解的類)和主配置類位于不同的包中,并且主配置類或者啟動類沒有使用 @ComponentScan 指定掃描這些包,那么在運行時就會報錯,因為Spring找不到這些組件。

主程序:

@SpringBootApplication
@ComponentScan(basePackages = "com.example")
public class DemoApplication {

    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
        Library library = context.getBean(Library.class);
        System.out.println(library.getBook().getTitle());
        System.out.println(library.getBook().getAuthor());
    }

}
Spring高手之路——深入理解注解驅(qū)動配置與XML配置的融合與區(qū)別

??@ComponentScan 不一定非要寫在主程序(通常是指 Spring Boot 的啟動類)上,它可以寫在任何配置類(標記有 @Configuration 注解的類)上。@ComponentScan 注解會告訴 Spring 從哪些包開始進行組件掃描。

??為了簡化配置,我們通常會將 @ComponentScan 放在主程序上,因為主程序一般會位于根包下,這樣可以掃描到所有的子包。這里為了演示,并沒有把主程序放在根目錄。

??我們上面說過,@ComponentScan只負責掃描和注冊Bean定義,只有需要某個Bean時,這個Bean才會實例化。

那怎么才能知道是不是需要這個Bean呢?

??我來給大家舉例子,并且還會說明Bean的創(chuàng)建順序問題,"需要某個Bean"通常體現(xiàn)在以下幾個方面:

  • 依賴注入(Dependency Injection): 如果一個BeanA的字段或者構(gòu)造方法被標注為@Autowired或者@Resource,那么Spring就會嘗試去尋找類型匹配的BeanB并注入到BeanA中。在這個過程中,如果BeanB還沒有被創(chuàng)建,那么Spring就會先創(chuàng)建BeanB的實例。
@Component
public class BeanA {
    @Autowired
    private BeanB beanB;
}

@Component
public class BeanB {
}

??BeanA依賴于BeanB。在這種情況下,當你嘗試獲取BeanA的實例時,Spring會首先創(chuàng)建BeanB的實例,然后把這個實例注入到BeanA中,最后創(chuàng)建BeanA的實例。在這個例子中,BeanB會先于BeanA被創(chuàng)建。

??這種方式的一個主要優(yōu)點是,我們不需要關(guān)心Bean的創(chuàng)建順序,Spring會自動解決這個問題。這是Spring IoC容器的一個重要特性,也是為什么它能夠使我們的代碼更加簡潔和易于維護的原因。

  • Spring框架調(diào)用: 有些情況下,Spring框架的一些組件或者模塊可能需要用到你定義的Bean。比如,如果你定義了一個@Controller,那么在處理HTTP請求時,Spring MVC就會需要使用到這個@Controller Bean。如果這個時候Bean還沒有被創(chuàng)建,那么Spring也會先創(chuàng)建它的實例。

假設我們有一個名為BookController的類,該類需要一個BookService對象來處理一些業(yè)務邏輯。

@Controller
public class BookController {
    @Autowired
    private BookService bookService;

    // 其他的控制器方法
}

BookService

@Service
public class BookService {
    @Autowired
    private BookMapper bookMapper;

    // 一些業(yè)務邏輯方法
}

Spring Boot應用程序啟動時,以下步驟將會發(fā)生:

  1. 首先,Spring框架通過@ComponentScan注解掃描類路徑,找到了BookController、BookServiceBookMapper等類,并為它們創(chuàng)建Bean定義,注冊到Spring的應用上下文中。

  2. 當一個請求到達并需要使用到BookController時,Spring框架會嘗試創(chuàng)建一個BookControllerBean實例。

  3. 在創(chuàng)建BookControllerBean實例的過程中,Spring框架發(fā)現(xiàn)BookController類中需要一個BookServiceBean實例(通過@Autowired注解指定),于是Spring框架會先去創(chuàng)建一個BookServiceBean實例。

  4. 同樣,在創(chuàng)建BookServiceBean實例的過程中,Spring框架發(fā)現(xiàn)BookService類中需要一個BookMapperBean實例(通過@Autowired注解指定),于是Spring框架會先去創(chuàng)建一個BookMapperBean實例。

  5. 在所有依賴的Bean都被創(chuàng)建并注入之后,BookControllerBean實例最終被創(chuàng)建完成,可以處理來自用戶的請求了。

在這個過程中,BookController、BookServiceBookMapper這三個Bean的創(chuàng)建順序是有嚴格要求的,必須按照他們之間的依賴關(guān)系來創(chuàng)建。只有當一個Bean的所有依賴都已經(jīng)被創(chuàng)建并注入后,這個Bean才能被創(chuàng)建。這就是Spring框架的IoC(控制反轉(zhuǎn))和DI(依賴注入)的機制。

  • 手動獲?。?/strong> 如果你在代碼中手動通過ApplicationContext.getBean()方法獲取某個Bean,那么Spring也會在這個時候創(chuàng)建對應的Bean實例,如果還沒有創(chuàng)建的話。

??總的來說,"需要"一個Bean,是指在運行時有其他代碼需要使用到這個Bean的實例,這個"需要"可能來源于其他Bean的依賴,也可能來源于框架的調(diào)用,或者你手動獲取。在這種需要出現(xiàn)時,如果對應的Bean還沒有被創(chuàng)建,那么Spring就會根據(jù)之前通過@ComponentScan等方式注冊的Bean定義,創(chuàng)建對應的Bean實例。

5.2 xml中啟用component-scan組件掃描

對應于 @ComponentScanXML 配置是 <context:component-scan> 標簽

<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">

    <context:component-scan base-package="com.example" />

</beans>

??在這段 XML 配置中,<context:component-scan> 標簽指定了 Spring 需要掃描 com.example 包及其子包下的所有類,這與 @ComponentScan 注解的功能是一樣的。

??注意:在使用 <context:component-scan> 標簽時,需要在 XML 配置文件的頂部包含 context 命名空間和相應的 schema 位置(xsi:schemaLocation)。

5.3 不使用@ComponentScan的組件掃描

如果我們不寫@ComponentScan注解,那么這里可以把主程序改為如下:

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext("com.example");
        Library library = context.getBean(Library.class);
        System.out.println(library.getBook().getTitle());
        System.out.println(library.getBook().getAuthor());
    }
}

??AnnotationConfigApplicationContext 的構(gòu)造方法中有一個是填寫basePackages路徑的,可以接受一個或多個包的名字作為參數(shù),然后掃描這些包及其子包。

Spring高手之路——深入理解注解驅(qū)動配置與XML配置的融合與區(qū)別

運行結(jié)果如下:

Spring高手之路——深入理解注解驅(qū)動配置與XML配置的融合與區(qū)別

??在這個例子中,Spring 將會掃描 com.example 包及其所有子包,查找并注冊所有的 Bean,達到和@ComponentScan注解一樣的效果。

??我們也可以手動創(chuàng)建一個配置類來注冊bean,那么想要運行得到一樣的效果,需要的代碼如下:

@Component
public class Book {
    
    private String title = "Java Programming";
    private String author = "Unknown";

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}
@Component
public class Library {
    
    private Book book;

    public Book getBook() {
        return book;
    }

    public void setBook(Book book) {
        this.book = book;
    }
}
@Configuration
public class LibraryConfiguration {
    @Bean
    public Book book() {
        Book book = new Book();
        book.setTitle("Java Programming");
        book.setAuthor("Unknown");
        return book;
    }

    @Bean
    public Library library() {
        Library library = new Library();
        library.setBook(book());
        return library;
    }
}

主程序:

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(LibraryConfiguration.class);
        Library library = context.getBean(Library.class);
        System.out.println(library.getBook().getTitle());
        System.out.println(library.getBook().getAuthor());
    }
}

??我們創(chuàng)建了一個配置類LibraryConfiguration,用于定義BookLibrary這兩個bean。然后以配置類LibraryConfiguration.class作為輸入的來創(chuàng)建SpringIOC容器(Spring應用上下文就是Spring IOC容器)。

運行結(jié)果和前面一樣。

??注意,在這個例子里,如果你寫@ComponentScan,并且SpringApplication.run(Application.class, args);作為Spring上下文,那么這里運行配置類需要去掉BookLibrary類的@Component注解,不然會報錯A bean with that name has already been defined。這是因為如果同時在 BookLibrary 類上使用了 @Component 注解,而且配置類LibraryConfiguration上使用了@Configuration注解,這都會被 @ComponentScan 掃描到,那么 BookLibrary的實例將會被創(chuàng)建并注冊兩次。正確的做法是,要么在配置類中通過 @Bean 注解的方法創(chuàng)建BookLibrary的實例,要么在 BookLibrary 類上寫 @Component 注解。如果不是第三方庫,我們一般選擇后者。

為什么要有配置類出現(xiàn)?所有的Bean上面使用@Component,用@ComponentScan注解掃描不就能解決了嗎?

??我們在使用一些第三方庫時,需要對這些庫進行一些特定的配置。這些配置信息,我們可能無法直接通過注解或者XML來完成,或者通過這些方式完成起來非常麻煩。而配置類可以很好地解決這個問題。通過配置類,我們可以在Java代碼中完成任何復雜的配置邏輯。

??假設你正在使用 MyBatis,在這種情況下可能需要配置一個SqlSessionFactory,在大多數(shù)情況下,我們無法(也不應該)直接修改第三方庫的代碼,所以無法直接在SqlSessionFactory類或其他類上添加@Configuration@Component等注解。為了能夠在Spring中使用和配置這些第三方庫,我們需要創(chuàng)建自己的配置類,并在其中定義@Bean方法來初始化和配置這些類的實例。這樣就可以靈活地控制這些類的實例化過程,并且可以利用Spring的依賴注入功能。

下面是一個使用@Configuration@Bean來配置MyBatis的例子:

@Configuration
@MapperScan("com.example.demo.mapper")
public class MyBatisConfig {

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources("classpath*:com/example/demo/mapper/*Mapper.xml")
        );
        return factoryBean.getObject();
    }
}

??sqlSessionFactory方法創(chuàng)建一個SqlSessionFactoryBean對象,并使用DataSourceSpring Boot默認為你配置的一個Bean)進行初始化。然后,它指定MyBatis mapper XML文件的位置,最后返回SqlSessionFactory對象。

??通過這種方式,你可以靈活地配置MyBatis,并將其整合到Spring應用中。這是一種比使用XML配置文件或僅僅依賴于自動配置更為靈活和強大的方式。


6. 組件注冊的其他注解

??@Controller, @Service, @Repository@Component 一樣的效果,它們都會被 Spring IoC 容器識別,并將類實例化為 Bean。讓我們來看這些注解:

  • @Controller:這個注解通常標注在表示表現(xiàn)層(比如 Web 層)的類上,如Spring MVC 中的控制器。它們處理用戶的 HTTP 請求并返回響應。雖然 @Controller@Component 在功能上是類似的,但 @Controller 注解的使用表示了一種語義化的分層結(jié)構(gòu),使得控制層代碼更加清晰。
Spring高手之路——深入理解注解驅(qū)動配置與XML配置的融合與區(qū)別
  • @Service:這個注解通常用于標注業(yè)務層的類,這些類負責處理業(yè)務邏輯。使用 @Service 注解表明該類是業(yè)務處理的核心類,使得代碼更具有語義化。
Spring高手之路——深入理解注解驅(qū)動配置與XML配置的融合與區(qū)別
  • @Repository:這個注解用于標記數(shù)據(jù)訪問層,也就是數(shù)據(jù)訪問對象或DAO層的組件。在數(shù)據(jù)庫操作的實現(xiàn)類上使用 @Repository 注解,這樣Spring將自動處理與數(shù)據(jù)庫相關(guān)的異常并將它們轉(zhuǎn)化為SpringDataAccessExceptions。
Spring高手之路——深入理解注解驅(qū)動配置與XML配置的融合與區(qū)別

??在實際開發(fā)中,幾乎很少看到@Repository,而是利用 MyBatis@Mapper@MapperScan 實現(xiàn)數(shù)據(jù)訪問,通常做法是,@MapperScan 注解用于掃描特定包及其子包下的接口,這些接口被稱為 Mapper 接口。Mapper 接口方法定義了 SQL 查詢語句的簽名,而具體的 SQL 查詢語句則通常在與接口同名的 XML 文件中定義。

??@MapperScan("com.example.**.mapper") 會掃描 com.example 包及其所有子包下的名為 mapper 的包,以及 mapper 包的子包。 ** 是一個通配符,代表任意深度的子包。

舉個例子,以下是一個 Mapper 接口的定義:

package com.example.demo.mapper;

public interface BookMapper {
    Book findBookById(int id);
}

對應的 XML 文件(通常位于 resources 目錄下,并且與接口在相同的包路徑中)

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.BookMapper">
    <select id="findBookById" parameterType="int" resultType="com.example.demo.Book">
        SELECT title, author FROM book WHERE id = #{id}
    </select>
</mapper>

??注意:在 XML 文件中的 namespace 屬性值必須與 Mapper 接口的全限定類名相同,<select> 標簽的 id 屬性值必須與接口方法名相同。

然后,在 Spring Boot 的主類上,我們使用 @MapperScan 注解指定要掃描的包:

@SpringBootApplication
@MapperScan("com.example.**.mapper")
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

??這樣,MyBatis 就會自動為 UserMapper 接口創(chuàng)建一個實現(xiàn)類(實際上是一個代理對象),并將其注冊到 Spring IOC 容器中,你就可以在你的服務類中直接注入 BookMapper 并使用它。

可能有小伙伴注意到了,這幾個注解中都有這么一段代碼

    @AliasFor(
        annotation = Component.class
    )
    String value() default "";

??@AliasForSpring 框架的注解,它允許你在一個注解屬性上聲明別名。在 Spring 的許多核心注解中,@AliasFor 用于聲明一個或多個別名屬性。

??舉個例子,在 @Controller, @Service, @Repository注解中,value() 方法上的 @AliasFor 聲明了一個別名屬性,它的目標注解是 @Component,具體的別名屬性是 value。也就是說,當我們在 @Controller, @Service, @Repository 注解上使用 value() 方法設置值時,實際上也就相當于在 @Component 注解上設置了 name 屬性的值。同時,這也表明了 @Controller, @Service, @Repository注解本身就是一個特殊的 @Component。


7. 將注解驅(qū)動的配置與XML驅(qū)動的配置結(jié)合使用

??有沒有這么一種可能,一個舊的Spring項目,里面有很多舊的XML配置,現(xiàn)在你接手了,想要全部用注解驅(qū)動,不想再寫XML配置了,那應該怎么兼容呢?

假設我們有一個舊的Spring XML配置文件 old-config.xml

<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 id="oldBean" class="com.example.OldBean" />

</beans>

這個文件定義了一個名為 “oldBean” 的bean

然后,我們編寫一個新的注解驅(qū)動的配置類:

package com.example;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

@Configuration
@ImportResource("classpath:old-config.xml")
public class NewConfig {

    @Bean
    public NewBean newBean() {
        return new NewBean();
    }
}

??在這個新的配置類中,我們使用 @ImportResource 注解來引入舊的XML配置文件,并定義了一個新的beannewBean”。@ImportResource("classpath:old-config.xml")告訴Spring在初始化AppConfig配置類時,去類路徑下尋找old-config.xml文件,并加載其中的配置。

??當我們啟動應用程序時,Spring會創(chuàng)建一個 ApplicationContext,這個 ApplicationContext 會包含 old-config.xml 文件中定義的所有beans(例如 “oldBean”),以及 NewConfig 類中定義的所有beans(例如 “newBean”)。

package com.example;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Application {

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(NewConfig.class);
        
        OldBean oldBean = context.getBean("oldBean", OldBean.class);
        NewBean newBean = context.getBean("newBean", NewBean.class);
        
        System.out.println(oldBean);
        System.out.println(newBean);
    }
}

??在以上的main方法中,我們通過使用AnnotationConfigApplicationContext并傳入NewConfig.class作為參數(shù),初始化了一個Spring上下文。在這個上下文中,既包含了從old-config.xml導入的bean,也包含了在NewConfig配置類中使用@Bean注解定義的bean

??所以,通過使用 @ImportResource,可以在新的注解配置中引入舊的XML配置,這樣就可以在不打斷舊的XML配置的基礎上逐步遷移至新的注解配置。

上面我們說到類路徑,什么是類路徑?

??resources目錄就是類路徑(classpath)的一部分。所以當我們說"類路徑下"的時候,實際上也包含了"resources"目錄。JVM在運行時,會把"src/main/resources"目錄下的所有文件和文件夾都添加到類路徑中。

??例如有一個XML文件位于"src/main/resources/config/some-context.xml",那么可以用以下方式來引用它:

@Configuration
@ImportResource("classpath:config/some-context.xml")
public class AppConfig {
    //...
}

這里可以描述為在類路徑下的’config’目錄中查找’some-context.xml’文件。

為什么說JVM在運行時,會把"src/main/resources"目錄下的所有文件和文件夾都添加到類路徑中?

??當你編譯并運行一個Java項目時,JVM需要知道去哪里查找.class文件以及其他資源文件。這個查找的位置就是所謂的類路徑(Classpath)。類路徑可以包含文件系統(tǒng)上的目錄,也可以包含jar文件。簡單的說,類路徑就是JVM查找類和資源的地方。

??在一個標準的Maven項目結(jié)構(gòu)中,Java源代碼通常在src/main/java目錄下,而像是配置文件、圖片、靜態(tài)網(wǎng)頁等資源文件則放在src/main/resources目錄下。

??當你構(gòu)建項目時,Maven(或者其他的構(gòu)建工具,如Gradle)會把src/main/java目錄下的.java文件編譯成.class文件,并把它們和src/main/resources目錄下的資源文件一起復制到項目的輸出目錄(通常是target/classes目錄)。

Spring高手之路——深入理解注解驅(qū)動配置與XML配置的融合與區(qū)別Spring高手之路——深入理解注解驅(qū)動配置與XML配置的融合與區(qū)別

??然后當你運行程序時,JVM會把target/classes目錄(即編譯后的src/main/javasrc/main/resources)添加到類路徑中,這樣JVM就可以找到程序運行所需的類和資源了。

??如果有一個名為application.properties的文件在src/main/resources目錄下,就可以使用類路徑來訪問它,就像這樣:classpath:application.properties。在這里classpath:前綴告訴JVM這個路徑是相對于類路徑的,所以它會在類路徑中查找application.properties文件。因為src/main/resources在運行時被添加到了類路徑,所以JVM能找到這個文件。


8. 思考總結(jié)

8.1 為什么我們需要注冊組件,這與Bean注冊有什么區(qū)別?

??在Spring框架中,Bean對象是由Spring IoC容器創(chuàng)建和管理的。通常Bean對象是應用程序中的業(yè)務邏輯組件,如數(shù)據(jù)訪問對象(DAO)或其他服務類。

??組件注冊,或者說在Spring中通過@Component或者其派生注解(@Service, @Controller, @Repository等)標記的類,是告訴Spring框架這個類是一個組件,Spring需要創(chuàng)建它的實例并管理它的生命周期。這樣當使用到這個類的時候,Spring就可以自動地創(chuàng)建這個類的實例并注入到需要的地方。

??Bean注冊和組件注冊其實是非常類似的,都是為了讓Spring知道它需要管理哪些類的實例。區(qū)別在于Bean注冊通常發(fā)生在配置類中,使用@Bean注解來明確地定義每一個Bean,而組件注冊則是通過在類上使用@Component或者其派生注解來告訴Spring,這個類是一個組件,Spring應該自動地為其創(chuàng)建實例。

8.2 什么是組件掃描,為什么我們需要它,它是如何工作的?

??組件掃描是Spring的一種機制,用于自動發(fā)現(xiàn)應用程序中的Spring組件,并自動地為這些組件創(chuàng)建Bean定義,然后將它們注冊到Spring的應用上下文中,我們可以通過使用@ComponentScan注解來啟動組件掃描。

??我們需要組件掃描是因為它可以大大簡化配置過程,我們不再需要為應用程序中的每個類都顯式地創(chuàng)建Bean。而是通過簡單地在類上添加@Component或者其派生注解,并啟動組件掃描,就可以讓Spring自動地為我們的類創(chuàng)建Bean并管理它們。

??組件掃描的工作過程如下:使用@ComponentScan注解并指定一個或多個包路徑時,Spring會掃描這些包路徑及其子包中的所有類。對于標記了@Component或者其派生注解的類,Spring會在應用上下文啟動時為它們創(chuàng)建Bean,并將這些Bean定義注冊到Spring的應用上下文中。當需要使用這些類的實例時,Spring就可以自動注入這些實例。文章來源地址http://www.zghlxwxcb.cn/news/detail-460717.html



歡迎一鍵三連~

有問題請留言,大家一起探討學習

----------------------Talk is cheap, show me the code-----------------------

到了這里,關(guān)于Spring高手之路——深入理解注解驅(qū)動配置與XML配置的融合與區(qū)別的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關(guān)文章

  • Spring高手之路16——解析XML配置映射為BeanDefinition的源碼

    Spring高手之路16——解析XML配置映射為BeanDefinition的源碼

    ?? Spring 框架中控制反轉(zhuǎn)( IOC )容器的 BeanDefinition 階段的具體步驟,主要涉及到 Bean 的定義、加載、解析,并在后面進行編程式注入和后置處理。這個階段是 Spring 框架中 Bean 生命周期的早期階段之一,對于理解整個 Spring 框架非常關(guān)鍵。 加載配置文件、配置類 ??在這

    2024年02月04日
    瀏覽(29)
  • Spring注解驅(qū)動開發(fā)之常用注解案例_告別在XML中配置Bean

    注解驅(qū)動開發(fā)就是不再使用Spring的bean.xml文件,改為純使用注解的方式開發(fā) @Configuration 此注解為配置類注解,相當于spring.xml文件,即配置類==配置文件 @Bean 給容器中注冊一個Bean;類型為返回值的類型,id默認是用方法名作為id 示例 Person類(后續(xù)注解配置類中都會以此類舉例),

    2024年01月21日
    瀏覽(27)
  • Spring高手之路-@Autowired和@Resource注解異同點

    Spring高手之路-@Autowired和@Resource注解異同點

    目錄 概述 相同點 1.都可以實現(xiàn)依賴注入 2.都可以用于注入任意類型的Bean 3.都支持通過名稱、類型匹配進行注入 不同點 1.來源不同。 2.包含的屬性不同 3.匹配方式(裝配順序)不同。 4.支持的注入對象類型不同 5.應用地方不同 @Autowired 和 @Resource 是在 Java 開發(fā)中用于實現(xiàn)依賴

    2024年02月03日
    瀏覽(26)
  • 后端進階之路——深入理解Spring Security配置(二)

    后端進階之路——深入理解Spring Security配置(二)

    「作者主頁」 :雪碧有白泡泡 「個人網(wǎng)站」 :雪碧的個人網(wǎng)站 「推薦專欄」 : ★ java一站式服務 ★ ★ 前端炫酷代碼分享 ★ ★ uniapp-從構(gòu)建到提升 ★ ★ 從0到英雄,vue成神之路 ★ ★ 解決算法,一個專欄就夠了 ★ ★ 架構(gòu)咱們從0說 ★ ★ 數(shù)據(jù)流通的精妙之道★ ★后端進

    2024年02月14日
    瀏覽(31)
  • Spring高手之路14——深入淺出:SPI機制在JDK與Spring Boot中的應用

    Spring高手之路14——深入淺出:SPI機制在JDK與Spring Boot中的應用

    ?? SPI ( Service Provider Interface ) 是一種服務發(fā)現(xiàn)機制,它允許第三方提供者為核心庫或主框架提供實現(xiàn)或擴展。這種設計允許核心庫/框架在不修改自身代碼的情況下,通過第三方實現(xiàn)來增強功能。 JDK原生的SPI : 定義和發(fā)現(xiàn) : JDK 的 SPI 主要通過在 META-INF/services/ 目錄下放置

    2024年02月09日
    瀏覽(26)
  • “深入理解SpringMVC的注解驅(qū)動開發(fā)“

    “深入理解SpringMVC的注解驅(qū)動開發(fā)“

    在現(xiàn)代的Web開發(fā)中,SpringMVC已經(jīng)成為了一個非常流行和強大的框架。它提供了許多注解來簡化開發(fā)過程,使得我們能夠更加專注于業(yè)務邏輯的實現(xiàn)。本文將深入探討SpringMVC的注解驅(qū)動開發(fā),重點關(guān)注常用注解、參數(shù)傳遞、返回值和頁面跳轉(zhuǎn)等方面。 1.1 @Controller @Controller注解用

    2024年02月09日
    瀏覽(22)
  • 深入理解Spring @RequestBody注解的用法與作用

    當我們使用 Spring Boot 框架處理客戶端提交的 HTTP 請求時,常常需要獲取請求參數(shù)并將其轉(zhuǎn)換為相應的 Java 對象。@RequestBody 注解可以幫助我們實現(xiàn)這個目標,它用于從 HTTP 請求體中獲取請求參數(shù),并將其轉(zhuǎn)換為指定的 Java 對象。本篇博客將介紹 @RequestBody 注解的基本用法和注意

    2024年02月15日
    瀏覽(33)
  • 深入理解Spring的@Async注解:實現(xiàn)異步方法調(diào)用

    在當今高速發(fā)展的應用開發(fā)領域,對于提升系統(tǒng)性能和響應能力的需求越來越迫切。而異步編程作為一種解決方案,已經(jīng)成為現(xiàn)代應用開發(fā)中的一項重要技術(shù)。本篇博客將帶您深入探究 Java 中的 @Async 注解,揭示其強大的異步執(zhí)行能力和精妙的實現(xiàn)機制。 異步編程是一種編程

    2024年02月05日
    瀏覽(26)
  • 深入理解Spring AOP注解:@DataScope與@DataSource

    在Spring AOP中,注解的使用扮演著重要角色,它們可以幫助我們明確定義切面、切點和增強處理。在本文中,我們將深入探討RuoYi框架兩個自定義注解:@DataScope和@DataSource。 定義注解 首先,我們定義一個名為@DataScope的注解,用于在特定的方法上實現(xiàn)數(shù)據(jù)范圍過濾等功能。 定義

    2024年02月16日
    瀏覽(32)
  • 深入理解 Spring 中的 @RequestBody 和 @ResponseBody 注解及其區(qū)別

    在現(xiàn)代的 Web 開發(fā)中,處理 HTTP 請求和響應是不可或缺的任務。Spring Framework 提供了豐富的功能來簡化這些任務,并使開發(fā)人員能夠更專注于業(yè)務邏輯。在本文中,我們將深入探討 Spring 中的 @RequestBody 和 @ResponseBody 注解,以及它們之間的區(qū)別。 @RequestBody 注解是 Spring 提供的一

    2024年02月14日
    瀏覽(29)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包