Spring Boot全註解下的IOC

目錄

1.IOC容器簡介

2.裝配Bean

2.1 通過掃描裝配Bean

2.2 自定義第三方Bean

3.依賴注入

4.生命週期

5.使用屬性文件

6.條件裝配Bean

7.Bean的作用域

8.@Profile

9.引入XML配置的Bean

10.Spring EL表達式


IOC(控制反轉)是Spring的核心,可以說Spring是一種基於IOC容器編程的框架。因爲Spring Boot是基於註解的開發Spring IOC,所以我們使用全註解的方式講述Spring IOC技術。

1.IOC容器簡介

SpringIOC容器是一個管理Bean的容器,在Spring的定義中,它要求所有的IOC容器都需要實現接口BeanFactory,它是一個頂級的容器接口。BeanFactory的實現代碼如下;

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;

public interface BeanFactory {
    //前綴
    String FACTORY_BEAN_PREFIX = "&";
    //多個getBean方法
    Object getBean(String var1) throws BeansException;

    <T> T getBean(String var1, Class<T> var2) throws BeansException;

    <T> T getBean(Class<T> var1) throws BeansException;

    Object getBean(String var1, Object... var2) throws BeansException;

    <T> T getBean(Class<T> var1, Object... var2) throws BeansException;
    //是否包含Bean
    boolean containsBean(String var1);
    //是否是單例
    boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
    //是否原型
    boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
    //是否類型匹配
    boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
    //獲取Bean類型
    Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
    //獲取Bean別名
    String[] getAliases(String var1);
}

Spring IOC容器中,默認的情況下,Bean都是以單例存在的,也就是說getBean方法返回的都是同一個對象。isSingleton方法則判斷Bean是否在Spring IOC中爲單例。與isSingleton相反的是isPrototype方法,如果它返回的是true,那麼我們使用getBean方法獲取Bean的時候,Spring IOC容器就會創建一個新的Bean返回給調用者。

由於BeanFactory的功能還不夠強大,因此Spring在BeanFactory的基礎上,設計了更爲高級的接口ApplicationContext。它是BeanFactory的子接口之一,在Spring的體系中BeanFactory和ApplicationContext是最重要的兩個接口。在Spring中,我們使用的大部分的Spring IOC容器都是ApplicationContext接口的實現類,它們的關係如下所示:

ApplicationContext接口通過繼承上級接口,進而繼承BeanFactory接口,但是在BeanFactory的基礎上,擴展了消息國際化接口、環境可配置接口、應用事件發佈接口和資源模式解析接口,所以它的功能會更爲強大。

爲了貼近Spring Boot的需要,這裏主要介紹一個基於註解的IOC容器:AnnotationConfigApplicationContext,它是一個基於註解的IOC容器。Spring Boot裝配和獲取Bean的方法和該容器如出一轍。首先看如下簡單的實例:

定義一個pojo:

package com.martin.config.chapter3.pojo;

import lombok.Data;

/**
 * @author: martin
 * @date: 2019/10/27 17:33
 * @description:
 */
@Data
public class User {
    private Long id;
    private String userName;
    private String note;
}

定義Java配置文件:

package com.martin.config.chapter3.config;

import com.martin.config.chapter3.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author: martin
 * @date: 2019/10/27 17:39
 * @description:
 */
@Configuration
public class AppConfig {
    @Bean("user")
    public User initUser() {
        User user = new User();
        user.setId(1L);
        user.setUserName("martin");
        user.setNote("note_1");
        return user;
    }
}

這裏@Configuration代表這是一個Java配置文件,Spring的容器會根據它來生成IOC容器去裝配Bean;@Bean代表將initUser方法返回的POJO裝配到IOC容器中,而其屬性name定義了這個Bean的名稱,如果沒有配置它,則將方法名稱“initUser”作爲Bean的名稱保存到Spring IOC容器中。最後,我們使用AnnotationConfigApplicationContext來構建自己的IOC容器,代碼清單如下:

package com.martin.config.chapter3;

import com.martin.config.chapter3.config.AppConfig;
import com.martin.config.chapter3.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author: martin
 * @date: 2019/10/27 18:57
 * @description:
 */
public class IocTest {
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        User user = ctx.getBean(User.class);
        System.out.println(user.getId());
    }
}

2.裝配Bean

2.1 通過掃描裝配Bean

除了使用註解@Bean注入Spring IOC容器,我們還可以使用掃描裝配Bean到IOC容器中,對於掃描裝配而言使用的註解是@Component和@ComponentScan。@Component是標明哪個類被掃描進入Spring IOC容器,而@ComponentScan則是標明採用何種策略去掃描裝配Bean。User使用@Component的實現代碼如下:

package com.martin.config.chapter3.pojo;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @author: martin
 * @date: 2019/10/27 17:33
 * @description:
 */
@Data
@Component("user")
public class User {
    @Value("1")
    private Long id;
    @Value("martin")
    private String userName;
    @Value("note")
    private String note;
}

這裏的註解@Component表明這個類將被Spring IOC容器掃描裝配,其中配置的“user”則是作爲Bean的名稱。如果不配置這個字符串,IOC容器會把類名的第一個字母作爲小寫,其他不變作爲Bean名稱放入到IOC容器中;註解@Value則指定具體的值,使得Spring IOC給與對應的屬性注入對應的值。

爲了讓IOC容器能裝配User這個類,需要改造AppConfig,代碼如下:

package com.martin.config.chapter3.config;

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

/**
 * @author: martin
 * @date: 2019/10/27 17:39
 * @description:
 */
@Configuration
@ComponentScan
public class AppConfig {
}

這裏加入了@ComponentScan,意味着它會進行自動掃描,但是它只會掃描類AppConfig所在的當前包和其子包,User類不屬於AppConfig的包或子包中的類,因此無法掃描到。如果想被掃描到,可以自定義掃描的包,可以通過basePackages定義掃描的包名,還可以通過basePackageClasses定義掃描的類。代碼如下:

@ComponentScan("com.martin.config.chapter3.pojo.*")
@ComponentScan(basePackages = "com.martin.config.chapter3.pojo.*")
@ComponentScan(basePackageClasses = User.class)

按照以上的配置策略,User類會被掃描到Spring IOC容器中。

2.2 自定義第三方Bean

現實的Java的應用往往需要引入許多來自第三方的包,並且希望把第三方包的類對象也放入到Spring IOC容器中,這時@Bean註解就可以發揮作用了。例如我們定義DHCP數據源,POM文件如下:

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-dbcp2</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

這樣DHCP和數據庫驅動就被加入到了項目中,接着將使用它提供的機制來生成數據源。代碼如下:

package com.martin.config.chapter3.config;

import org.apache.commons.dbcp2.BasicDataSourceFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.util.Properties;

/**
 * @author: martin
 * @date: 2019/10/27 17:39
 * @description:
 */
@Configuration
public class AppConfig {
    @Bean("dataSource")
    public DataSource getDataSource() {
        Properties properties = new Properties();
        properties.setProperty("driver", "com.mysql.jdbc.Driver");
        properties.setProperty("url", "jdbc:mysql://localhost:3306/chapter3");
        properties.setProperty("username", "root");
        properties.setProperty("password", "123456");
        try {
            return BasicDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

這裏通過@Bean定義了其配置項name爲dataSource,IOC容器就會把它作爲對象名保存起來。

3.依賴注入

不同Bean之間的依賴被稱爲依賴注入,依賴注入主要使用@Autowired註解。例如我們注入一個user屬性:

  @Autowired
  private User user;

@Autowired註解也可以用到方法上:

@Autowired
public void setUser(User user) {
    this.user = user;
}

@Autowired是一個默認必須找到對應Bean的註解,如果不能確定其標註屬性一定會存在並且允許這個被標註的屬性爲null,那麼可以配置@Autowired屬性required爲false。

 @Autowired(required = false)
 private User user;

如果User的實現類有多個,比如管理員admin,普通用戶general ,此時單純使用@Autowired註解,IOC容器時無法區分採用哪個Bean實例注入。我們可以使用@Quelifier註解,與@Autowired組合在一起,通過類型和名稱一起找到Bean。

@Autowired
@Qualifier("admin")
private User user;

Spring IOC將會以類型和名稱一起去尋找對應的Bean進行注入。

4.生命週期

Bean的聲明週期過程,大致分爲Bean定義、Bean的初始化、Bean的生存期和Bean的銷燬4個部分,其中Bean定義過程大致如下:

  • Spring通過配置,如@ComponentScan定義的掃描路徑去找到帶有@Component的類,這個過程就是一個資源定位的過程
  • 一旦找到資源,那麼就開始解析,並且將定義的信息保存起來。注意,此時還沒有初始化Bean,也沒有Bean的實例,僅僅有Bean的定義
  • 把Bean定義發佈到Spring IOC容器中。

完成了這3步只是一個資源定位並將Bean的定義發佈到IOC容器的過程,還沒有Bean實例的生成,更沒有完成依賴注入。在默認情況下,接下來的步驟是完成Bean的實例化和依賴注入,這樣就能從IOC容器中獲取到一個Bean實例。如果我們設置lazyInit(懶加載)的值爲true,那麼Spring並不會在發佈Bean定義後馬上爲我們完成實例化和依賴注入,而是要等到真正使用到的時候纔開始實例化和依賴注入。

Spring在完成依賴注入之後,還提供了一系列的接口和配置來完成Bean的初始化過程,整個流程如下:

Spring IOC容器最低的要求是實現BeanFactory接口,而不是實現ApplicationContext接口。對於那些沒有實現ApplicationContext接口的容器,在生命週期對應的ApplicationContextAware定義的方法也不會調用,只有實現了ApplicationContext接口的容器,纔會在生命週期調用ApplicationContextAware所定義的setApplicationContext方法。爲了測試生命週期我們定義一個BussinessPerson類,代碼如下:

package com.martin.config.chapter3.service;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * @author: martin
 * @date: 2019/10/28 22:09
 * @description:
 */
@Component
public class BussinessPerson implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("調用BeanFactoryAware的setBeanFactory");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("調用BeanNameAware的setBeanName方法:" + name);
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("調用DisposableBean的destroy");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("調用InitializingBean的afterPropertiesSet");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("調用ApplicationContextAware的setApplicationContext");
    }

    @PostConstruct
    public void init() {
        System.out.println("調用@PostConstruct標識的方法");
    }

    @PreDestroy
    public void preDestroy() {
        System.out.println("調用@PreDestroy標識的方法");
    }
}

這樣,BussinessPerson 這個Bean就實現了生命週期中單個Bean可以實現的所有接口。爲了測試Bean的後置處理器,我們創建一個類BeanPostProcessorExample,該後置處理器將對所有的Bean都有效,代碼如下:

package com.martin.config.chapter3.service;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * @author: martin
 * @date: 2019/10/28 22:31
 * @description:
 */
@Component
public class BeanPostProcessorTest implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor調用before" + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor調用After" + beanName);
        return bean;
    }
}

運行Spring Boot應用程序,輸出結果如下:

調用BeanNameAware的setBeanName方法:bussinessPerson
調用BeanFactoryAware的setBeanFactory
調用ApplicationContextAware的setApplicationContext
BeanPostProcessor調用beforebussinessPerson
調用@PostConstruct標識的方法
調用InitializingBean的afterPropertiesSet
BeanPostProcessor調用AfterbussinessPerson
BeanPostProcessor調用beforedataSource
BeanPostProcessor調用AfterdataSource

對於Bean後置處理器(BeanPostProcessor)而言,它對所有的Bean都起作用,而其他的接口則是對於單個Bean起作用。有時候Bean的定義可能使用的是第三方的類,此時可以使用註解@Bean來配置自定義初始化和銷燬方法,代碼如下:

@Bean(initMethod='init',destroyMethod='destroy')

5.使用屬性文件

在Spring Boot中使用屬性文件,可以採用默認的application.properties,也可以使用自定義的配置文件。在Spring Boot中,我們在Maven中添加依賴:

 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-configuration-processor</artifactId>
     <optional>true</optional>
 </dependency>

有了該依賴,就可以直接使用application.properties文件爲我們工作了。配置文件如下:

database.driverName=com.mysql.jdbc.Driver
database.url=jdbc:mysql://localhost:3306/test
database.username=root
database.password=123456

我們使用Spring表達式的方式獲取配置的屬性值:

package com.martin.config.chapter3.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @author: martin
 * @date: 2019/11/2 17:23
 * @description:
 */
@Component
public class DataBaseProperties {
    @Value("${database.driverName}")
    private String driverName;
    @Value("${database.url}")
    private String url;
    private String password;
    private String userName;

    public String getDriverName() {
        return driverName;
    }

    public void setDriverName(String driverName) {
        this.driverName = driverName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getPassword() {
        return password;
    }

    @Value("${database.password}")
    public void setPassword(String password) {
        this.password = password;
    }

    public String getUserName() {
        return userName;
    }

    @Value("${database.username}")
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

通過Spring表達式@Value註解,讀取配置在屬性文件的內容。@Value註解既可以加載屬性,也可以加在方法上。

我們也可以使用註解@ConfigurationProperties來配置屬性,代碼如下:

package com.martin.config.chapter3.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @author: martin
 * @date: 2019/11/2 17:23
 * @description:
 */
@Component
@ConfigurationProperties("database")
public class DataBaseProperties {
    private String driverName;
    private String url;
    private String password;
    private String userName;

    public String getDriverName() {
        return driverName;
    }

    public void setDriverName(String driverName) {
        this.driverName = driverName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

這裏在@ConfigurationProperties中配置的字符串database,將與POJO的屬性名稱組成屬性屬性的全限定名去配置文件裏查找,這樣就能將對應的屬性讀取到POJO當中。

有時候我們會覺得如果把所有的屬性配置到放置到application.properties中,這個文件將會有很多屬性內容。爲了更好的配置,我們將數據庫的屬性配置到jdbc.properties中,然後使用@PropertySource去定義對應的屬性文件,把它加載到Spring的上下文中。代碼如下所示:

package com.martin.config;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;

/**
 * 配置啓動類
 *
 * @author martin
 * @create 2019-01-03 下午 11:20
 **/
@SpringBootApplication
@PropertySource(value = {"classpath:jdbc.properties"}, ignoreResourceNotFound = true)
public class SpringBootConfigApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootConfigApplication.class, args);
    }
}

value可以配置多個配置文件,使用classpath前綴,意味着去類文件路徑下找到屬性文件;ignoreResourceNotFound則是是否忽略配置文件找不到的問題,默認值是false,也就是找不到屬性文件就會報錯。

6.條件裝配Bean

有時候我們希望IOC容器在某些條件滿足下才去裝配Bean,例如我們要求在數據庫的配置中,驅動名、url、賬號和密碼都存在的情況下才去連接數據庫。此時我們需要使用@Conditional註解和實現Condition接口的類。代碼如下:

package com.martin.config.chapter3.config;

import org.apache.commons.dbcp2.BasicDataSourceFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.util.Properties;

/**
 * @author: martin
 * @date: 2019/10/27 17:39
 * @description:
 */
@Configuration
public class AppConfig {
    @Bean("dataSource")
    @Conditional(DatabaseConditional.class)
    public DataSource getDataSource(@Value("${database.driverName") String driver,
                                    @Value("${database.url") String url,
                                    @Value("${database.username") String username,
                                    @Value("${database.password") String password) {
        Properties properties = new Properties();
        properties.setProperty("driver", driver);
        properties.setProperty("url", url);
        properties.setProperty("username", username);
        properties.setProperty("password", password);
        try {
            return BasicDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

加入了@Conditionnal註解,並且配置了類DatabaseConditional,那麼這個類就必須實現Condition接口。代碼如下:

package com.martin.config.chapter3.config;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

/**
 * @author: martin
 * @date: 2019/11/2 20:08
 * @description:
 */
public class DatabaseConditional implements Condition {
    /**
     * 數據庫裝配條件
     *
     * @param context  條件上下文
     * @param metadata 註釋類型的元數據
     * @return true裝配Bean,否則不裝配
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        //判斷屬性文件是否存在對應的數據庫配置
        return environment.containsProperty("database.driverName")
                && environment.containsProperty("database.url")
                && environment.containsProperty("database.username")
                && environment.containsProperty("database.password");
    }
}

maches方法讀取上下文環境,判斷是否已經配置了對應的數據庫信息。當都配置好了以後返回true,Spring會裝配數據庫連接池的Bean,否則不裝配。

7.Bean的作用域

IOC容器最頂級接口BeanFactory中,可以看到isSingleton和isPrototype兩個方法。其中,如果isSingleton方法如果返回true,則Bean在IOC容器中以單例存在,這也是Spring IOC容器的默認值。如果isPrototype方法返回true,則當我們每次獲取Bean的時候,IOC容器都會創建一個新的Bean。除了這些,Bean還存在其他類型的作用域:

對於application作用域,完全可以使用單例來代替。

作用域的定義使用@Scope註解,實例代碼如下:

package com.martin.config.chapter3.service;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;

/**
 * @author: martin
 * @date: 2019/11/2 22:25
 * @description:
 */
@Component
@Scope(WebApplicationContext.SCOPE_REQUEST)
public class ScopeBean {
}

8.@Profile

在企業開發的過程中,項目往往需要面臨開發環境,測試環境,愈發環境和生產環境的切換,而每一套環境的上下文是不一樣的。例如,它們會有各自的數據庫資源,這樣就需要我們再不同的數據庫之前進行切換。爲了方便,Spring提供了Profile機制,使得我們可以方便地實現各個環境之間的切換。

在Spring中存在兩個配置參數可以提供給我們修改啓動Profile機制,一個是spring.profiles.active,另外一個是spring.profiles.default。在兩個屬性參數都沒有配置的情況下,Spring將不會啓動Profile機制。Spring先判斷是否存在spring.profiles.active配置之後,再去查找spring.profiles.default配置,所以spring.profiles.active優先級大於spring.profiles.default。

在Java項目啓動時,我們配置如下就能夠啓動Profile機制:

JAVA_OPTS=“-Dspring.profiles.active=dev”

在Spring Boot的規則中,假設把選項-Dspring.profiles.active配置的值記爲{profile},它就會用application-{profile}.properties文件去代替原來默認的application.properties文件,然後啓動Spring Boot的程序。

9.引入XML配置的Bean

儘管Spring Boot建議使用註解和掃描配置Bean,但是它並不拒絕使用XML配置Bean。如果我們想在Spring Boot中使用XML對Bean進行配置,可以使用註解@ImportResource,通過它可以引入對應的XML文件,用以加載Bean。實例代碼如下:

Configuration
@ImportResource(value = {"classpath:spring-job.xml"})
public class AppConfig {

}

這樣就可以引入對應的XML,從而將XML定義的Bean裝配到IOC容器中。

10.Spring EL表達式

在前面的代碼中,我們是在沒有任何運算規則的情況下裝配Bean的。爲了更加靈活,Spring EL表達式爲我們提供了強大的運算規則來更好的裝配Bean。

EL表達式最常用的是讀取配置屬性文件中的值,例如:

@Value("${database.driverName}")

除此之外,它還能夠調用方法,例如,記錄Bean的初始化時間:

    @Value("#{T(System).currentTimeMillis()}")
    private Long time;

這裏採用#{.......}代表啓用Spring表達式,它將具有運算的功能;T(......)代表的是引入類;System是java.lang.*包的類,這是java 默認加載的包,可以不用寫全限定名。如果是其他的包,需要寫出全限定名才能引用類。此外EL表達式支持多種賦值方式,代碼如下:

package com.martin.config.chapter3.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @author: martin
 * @date: 2019/11/2 23:06
 * @description:
 */
@Component
public class SpringEl {
    @Value("${database.driverName}")
    private String driver;
    @Value("#{T(System).currentTimeMillis()}")
    private Long time;
    /**
     * 使用字符串直接賦值
     */
    @Value("#{'使用Spring EL賦值字符串'}")
    private String str;
    /**
     * 科學計數法賦值
     */
    @Value("#{9.3E3}")
    private Double d;
    /**
     * 賦值浮點數
     */
    @Value("#{3.14}")
    private float pi;
    /**
     * 使用其他Bean的屬性來賦值
     */
    @Value("#{beanName.str}")
    private String otherBeanProp;

    /**
     * 使用其他Bean的屬性來賦值,轉換爲大寫
     */
    @Value("#{beanName.str?.toUpperCase()}")
    private String otherBeanPropUpperCase;
    /**
     * 數學運算
     */
    @Value("#{1+2}")
    private int run;
    /**
     * 浮點數比較運算
     */
    @Value("#{beanName.pi == 3.14f}")
    private boolean piFlag;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章