天天看點

spring(基于注解的 IOC 配置)1. 基于注解的改造2. 常用注解3. spring 的純注解配置4. Spring 整合 Junit

1. 基于注解的改造

使用@Component 注解配置管理的資源

@Component("accountService")
public class AccountServiceImpl implements IAccountService {
    private IAccountDao accountDao;
    public void setAccountDao(IAccountDao accountDao) {
        this.accountDao = accountDao;
    }
}


@Component("accountDao")
public class AccountDaoImpl implements IAccountDao {
    private DBAssit dbAssit;
}
           
當我們使用注解注入時,set 方法不用寫

建立 spring 的 xml 配置檔案并開啟對注解的支援

基于注解整合時,導入限制時需要多導入一個 context 名稱空間下的限制。
<?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 建立容器時要掃描的包 -->
    <context:component-scan base-package="org.woster"></context:component-scan>
    <!-- 配置 dbAssit -->
    <bean id="dbAssit" class="org.woster.dbassit.DBAssit">
        <property name="dataSource" ref="dataSource"></property>
    </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:///test"></property>
        <property name="user" value="root"></property>
        <property name="password" value="1234"></property>
    </bean>
</beans>
           

2. 常用注解

2.1 用于建立對象的

@Component

  • 作用:把資源讓 spring 來管理。相當于在 xml 中配置一個 bean。
  • 屬性:
    • value:指定 bean 的 id。如果不指定 value 屬性,預設 bean 的 id 是目前類的類名。首字母小寫。

@Controller @Service @Repository

他們三個注解都是針對一個的衍生注解,他們的作用及屬性都是一模一樣的。

他們隻不過是提供了更加明确的語義化。

  • @Controller:一般用于表現層的注解。
  • @Service:一般用于業務層的注解。
  • @Repository:一般用于持久層的注解。
如果注解中有且隻有一個屬性要指派時,且名稱是 value,value 在指派是可以不寫。

2.2 用于注入資料的

@Autowired

  • 自動按照類型注入。當使用注解注入屬性時,set 方法可以省略。它隻能注入其他 bean 類型。當有多個類型比對時,使用要注入的對象變量名稱作為 bean 的 id,在 spring 容器查找,找到了也可以注入成功。找不到就報錯。

@Qualifier

  • 在自動按照類型注入的基礎之上,再按照 Bean 的 id 注入。它在給字段注入時不能獨立使用,必須和@Autowire 一起使用;但是給方法參數注入時,可以獨立使用。
  • value:指定 bean 的 id。

@Resource

  • 直接按照 Bean 的 id 注入。它也隻能注入其他 bean 類型。
  • name:指定 bean 的 id。

@Value

  • 注入基本資料類型和 String 類型資料的
  • value:用于指定值

2.3 用于改變作用範圍的

@Scope

  • 指定 bean 的作用範圍。
  • value:指定範圍的值。取值:singleton prototype request session globalsession

2.4 和生命周期相關的

@PostConstruct

  • 用于指定初始化方法。

@PreDestroy

  • 用于指定銷毀方法。

2.5 關于 Spring 注解和 XML 的選擇問題

  • 注解的優勢:配置簡單,維護友善(我們找到類,就相當于找到了對應的配置)。
  • XML 的優勢:修改時,不用改源碼。不涉及重新編譯和部署
基于XML配置 基于注解配置
Bean定義

<bean id="…“

class=”…"/>

@Component

衍生類@Repository

@Service @Controller

Bean名稱

通過id或name

指定

@Component(“person”)
Bean注入

<property>或者

通過p名命空間

@Autowired按類型注入

@Qualifier按名稱注入

生命過程、

Bean作用範圍

init-method

destroy-method

範圍scope屬性

@PostConstruct初始化

@PreDestroy銷毀

@Scope設定作用範圍

适合場景

Bean來自第三

方,使用其他

Bean的實作類由使用者自己

開發

基于注解的 spring IoC 配置中,bean 對象的特點和基于 XML 配置是一模一樣的。

3. spring 的純注解配置

3.1 待改造的問題

我們發現,之是以我們現在離不開 xml 配置檔案,是因為我們有一句很關鍵的配置:

<!-- 告知spring架構在,讀取配置檔案,建立容器時,掃描注解,依據注解建立對象,并存入容器中 -->
<context:component-scan base-package="org.woster"></context:component-scan>
           

如果他要也能用注解配置,那麼我們就離脫離 xml 檔案又進了一步。

另外,資料源和 JdbcTemplate 的配置也需要靠注解來實作。

<!-- 配置 dbAssit -->
<bean id="dbAssit" class="org.woster.dbassit.DBAssit">
    <property name="dataSource" ref="dataSource"></property>
</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:///spring_day02"></property>
    <property name="user" value="root"></property>
    <property name="password" value="1234"></property>
</bean>
           

3.2 新注解說明

@Configuration

  • 用于指定目前類是一個 spring 配置類,當建立容器時會從該類上加載注解。擷取容器時需要使用AnnotationApplicationContext(有@Configuration 注解的類.class)。
  • value:用于指定配置類的位元組碼
@Configuration
public class SpringConfiguration {
}
           

@ComponentScan

  • 用于指定 spring 在初始化容器時要掃描的包。作用和在 spring 的 xml 配置檔案中的:<context:component-scan base-package=“org.woster”/>是一樣的。
  • basePackages:用于指定要掃描的包。和該注解中的 value 屬性作用一樣。
@Configuration
@ComponentScan("org.woster")
public class SpringConfiguration {
}
           

@Bean

  • 該注解隻能寫在方法上,表明使用此方法建立一個對象,并且放入 spring 容器。
  • name:給目前@Bean 注解方法建立的對象指定一個名稱(即 bean 的 id)。
public class JdbcConfig {
    /**
    * 建立一個資料源,并存入 spring 容器中
    * @return
    */
    @Bean(name="dataSource")
    public DataSource createDataSource() {
        try {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setUser("root");
            ds.setPassword("1234");
            ds.setDriverClass("com.mysql.jdbc.Driver");
            ds.setJdbcUrl("jdbc:mysql:///test");
            return ds;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    /**
    * 建立一個 DBAssit,并且也存入 spring 容器中
    * @param dataSource
    * @return
    */
    @Bean(name="dbAssit")
    public DBAssit createDBAssit(DataSource dataSource) {
        return new DBAssit(dataSource);
    }
}
           

@PropertySource

  • 用于加載.properties 檔案中的配置。例如我們配置資料源時,可以把連接配接資料庫的資訊寫到properties 配置檔案中,就可以使用此注解指定 properties 配置檔案的位置。
  • value[]:用于指定 properties 檔案位置。如果是在類路徑下,需要寫上 classpath:
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;
    /**
    * 建立一個資料源,并存入 spring 容器中
    * @return
    */
    @Bean(name="dataSource")
    public DataSource createDataSource() {
        try {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driver);
            ds.setJdbcUrl(url);
            ds.setUser(username);
            ds.setPassword(password);
            return ds;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
           

jdbc.properties 檔案

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=1234
           

@Import

  • 用于導入其他配置類,在引入其他配置類時,可以不用再寫@Configuration 注解。當然,寫上也沒問題。
  • value[]:用于指定其他配置類的位元組碼。
@Configuration
@ComponentScan(basePackages = "org.woster.spring")
@Import({ JdbcConfig.class})
public class SpringConfiguration {
}
@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig{
}
           

3.3 通過注解擷取容器

4. Spring 整合 Junit

4.1 測試類中的問題和解決思路

問題

在測試類中,每個測試方法都有以下兩行代碼:

ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
IAccountService as = ac.getBean("accountService",IAccountService.class);
           

這兩行代碼的作用是擷取容器,如果不寫的話,直接會提示空指針異常。是以又不能輕易删掉。

解決思路分析

針對上述問題,我們需要的是程式能自動幫我們建立容器。一旦程式能自動為我們建立 spring 容器,我們就無須手動建立了,問題也就解決了

我們都知道,junit 單元測試的原理(在 web 階段課程中講過),但顯然,junit 是無法實作的,因為它自己都無法知曉我們是否使用了 spring 架構,更不用說幫我們建立 spring 容器了。不過好在,junit 給我們暴露了一個注解,可以讓我們替換掉它的運作器。

這時,我們需要依靠 spring 架構,因為它提供了一個運作器,可以讀取配置檔案(或注解)來建立容器。我們隻需要告訴它配置檔案在哪就行了。

4.2 配置步驟

第一步:導入整合 junit 的必備 jar 坐标

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.1.9.RELEASE</version>
</dependency>
           

第二步:使用@RunWith 注解替換原有運作器

@RunWith(SpringJUnit4ClassRunner.class)
public class AccountServiceTest {
}
           

第三步:使用@ContextConfiguration 指定 spring 配置檔案的位置

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:bean.xml"})
public class AccountServiceTest {
}
           

@ContextConfiguration 注解:

  • locations 屬性:用于指定配置檔案的位置。如果是類路徑下,需要用 classpath:表明
  • classes 屬性:用于指定注解的類。當不使用 xml 配置時,需要用此屬性指定注解類的位置。

第四步:使用@Autowired 給測試類中的變量注入資料

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:bean.xml"})
public class AccountServiceTest {
    @Autowired
    private IAccountService as ;
}
           

繼續閱讀