3.5运行时值注入

本文探讨了Spring框架中的依赖注入,如何通过属性占位符和SpEL表达式动态设置Bean属性,以及如何使用`@Profile`和`Environment`进行环境切换。重点介绍了配置文件中的`disc.title`和`disc.artist`注入方式,以及Spring Expression Language (SpEL)的强大功能应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

讨论依赖注入的时候,我们通常所讨论的是将一个Bean的引用注入到另一个Bean的属性或构造器参数中。它通常来讲指的是将一个对象与另一个对象关联。

另一个方面,将一个值注入到Bean的属性或者构造器参数中!

public class SgtPeppers implements CompactDisc, BeanNameAware
{

    private String title = "Sgt. Pepper's Lonely Hearts Club Band";
    private String artist = "The Beatles";

    public void play() {
        System.out.println("Playing" + title + "by" + artist);
    }

    public void setBeanName(String s) {
        System.out.println(s);
    }
}

之前我们是使用硬编码的模式,把string写死。

我们有的时候想要在运行的时候再确定到底想要什么值注入进去。

Spring有两种在运行的时候求值的方式:

  1. 属性占位符
  2. spring表达式

3.5.1 注入外部的值

需要注入的值可以放在一个外部的properties文件当中,这些属性文件会加载到Spring的Environment中

disc.title=Sgt. Pepper's Lonely Hearts Club Band
disc.artist=The Beatles

运行是注入:

@Configuration
@PropertySource("classpath:app.properties")
public class ExpressiveConfig {

    @Autowired
    Environment environment;

    @Bean
    public BlankDisc disc (){
        return new BlankDisc(environment.getProperty("disc.title"), environment.getProperty("disc.artist"));
    }
}

深入学习Spring的environment

getProperty()并不是唯一一个获取属性的方法:

String getProperty(String key)

String getProperty(String key, String defalutValue) //在获取不到的时候返回默认值

T getProperty(String key, Class<T> type) //可以进行类型转换,传入Integer.class就可以返回Int

T getProperty(String key, Class<T> type, T defaultValue)

 

除了属性相关功能之外,

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ExpressiveConfig.class)
@ActiveProfiles("dev") //我们开启dev
//@ComponentScan
public class TestAdv {

    @Autowired
    @Qualifier("disc")
    CompactDisc compactDisc;

    @Test
    public void testFun() {
        System.out.println(compactDisc);
        compactDisc.play();
    }

}

@Configuration
@PropertySource("classpath:app.properties")
public class ExpressiveConfig {

    @Autowired
    Environment environment;

    @Bean
    public BlankDisc disc (){
        System.out.println(Arrays.deepToString(environment.getActiveProfiles()));
        System.out.println(environment.acceptsProfiles("dev"));
        return new BlankDisc(environment.getProperty("disc.title"), environment.getProperty("disc.artist"));
    }
}

运行结果

[dev]
true
SPEL.BlankDisc@6c80d78a
Playing Sgt. Pepper's Lonely Hearts Club Band by The Beatles
--------track------

我们开启了dev这个环境后,在env里面就可以获得profile [dev], acceptProfiles 这个方法则是用来判断你传入的字符串数组,这里是【dev】是不是被激活的。

之前那个conditional的例子里面用到过,

class ProfileCondition implements Condition {

	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
		if (attrs != null) {
			for (Object value : attrs.get("value")) {
				if (context.getEnvironment().acceptsProfiles((String[]) value)) {
					return true;
				}
			}
			return false;
		}
		return true;
	}

}

从context中可以拿到env,就像我们上面看的那样,是环境。

从metaData,可以获取这个Bean上所有的注解,getAllAnnotationAttributes拿到所有profile相关的注解,然后再拿value,就可以拿到profile的数组

最后调用acceptProfile来判断@Profile上面标注的环境和context里面的环境是不是一样的,一样的才产生这个bean。

3.5.2解析属性占位符

Spring一直支持将属性定义到外部的属性文件中,并使用占位符值将其插入到SpringBean中。${...}是占位符的形式,以下是例子,

   自动扫描
 public BlankDisc(@Value("${disc.title}") String title, @Value("${disc.artist}") String artist) {
        this.title = title;
        this.artist = artist;
    }

    手动声明

    @Bean
    public BlankDisc disc (@Value("${disc.title}") String title, @Value("${disc.artist}") String artist){
        System.out.println(Arrays.deepToString(environment.getActiveProfiles()));
        System.out.println(environment.acceptsProfiles("dev"));
//        return new BlankDisc(environment.getProperty("disc.title"), environment.getProperty("disc.artist"));
        return new BlankDisc(title, artist);
    }

3.5.3 使用Spring表达式语言进行装配

SpEL拥有很多特性,包括:

使用bean的id来引用bean;

调用方法和访问对象的属性;

对值进行算数,关系和逻辑运算;

正则表达式匹配;

集合操作

和占位符不同的是,Spring表达式需要放在 #{....}中 

例子:这个systemProperties是自带的变量,似乎需要放在虚拟机参数里面。-Ddisc.artist=li 放在外部的文件中似乎不管用???

SPEL 基础

  1. 表示字面值 #{3.1415}
  2. 引用bean、属性和方法
  3. 在表达式中使用类型
  4. Spel运算符
  5. 计算正则表达式
  6. 计算集合

2,引用bean属性和方法

@Component
public class CDPlayer {

    public CompactDisc compactDisc;

    public CDPlayer(@Value("#{blankDisc}") CompactDisc compactDisc) {
        this.compactDisc=compactDisc;
    }
}

    public CDPlayer(@Value("#{blankDisc}") CompactDisc compactDisc, @Value("#{blankDisc.getArtist()?.toUpperCase()}") String artist) {
        this.compactDisc=compactDisc;
        this.artist=artist;
    }

3,在表达式中使用类型

    public CDPlayer(@Value("#{blankDisc}") CompactDisc compactDisc, @Value("#{T(java.lang.Math).PI}") String artist) {
        this.compactDisc=compactDisc;
        this.artist=artist;
    }

4,SpEL运算符

   public CDPlayer(@Value("#{blankDisc ?: 'Rattle and Hum'}") CompactDisc compactDisc, @Value("#{T(java.lang.Math).PI}") String artist) {
        this.compactDisc=compactDisc;
        this.artist=artist;
    }

这个好像没有什么特别的,就只有上面的那个可以判断 ?:是不是空 如果是空的话就会返回'Rattle and Hum'

5,正则表达式

太复杂了,不赘述

6, 计算集合 

    @Value("#{jukeBox.songs[2].title}")
    String value;

    @Value("#{jukeBox.songs.$[artist == 'qu']}")
    Song list;

    @Value("#{jukeBox.songs.^[artist == 'qu']}")
    Song list;

    @Value("#{jukeBox.songs.![artist]}")
    List<String> names;

    @Value("#{jukeBox.songs.?[artist == 'qu']}")
    List<Song> names;

SPEL可以通过【】来获取集合中的元素,第二个是可以获取艺术家是qu的最后一个元素,第三个是第一个元素,第四是投影,可以用song.artist新建一个list,第五个是过滤一个艺术家是qu的list。

Spring 表达式很强大,但是也不要整的太复杂,毕竟不要debug。。。。

以下是我现在的web.config <?xml version="1.0" encoding="utf-8"?> <!-- 有关如何配置 ASP.NET 应用程序的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkId=301879 --> <configuration> <appSettings> <add key="webpages:Version" value="3.0.0.0" /> <add key="webpages:Enabled" value="false" /> <add key="ClientValidationEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true" /> <add key="PostUserID" value="Allgo" /> <add key="PostPassword" value="Allgo2024" /> <!-- Allgo Database Connection Configuration --> <add key="SeverIP" value="47.250.46.2,1433" /> <add key="Database" value="VMSDB" /> <add key="UserId" value="sa" /> <add key="PWD" value="Allgo@2020" /> <!-- Common Parameters Configuration --> <add key="TimeOutValue" value="10" /> <add key="DateFormat" value="M/d/yyyy" /> <add key="DateTimeFormat" value="M/d/yyyy HH:mm:ss.fff" /> <add key="TimeFormat" value="HH:mm:ss" /> </appSettings> <system.web> <compilation targetFramework="4.7.2" /> <httpRuntime targetFramework="4.7.2" /> </system.web> <system.webServer> <handlers> <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> <remove name="OPTIONSVerbHandler" /> <remove name="TRACEVerbHandler" /> <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> </handlers> </system.webServer> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Antlr3.Runtime" publicKeyToken="eb42632606e9261f" /> <bindingRedirect oldVersion="0.0.0.0-3.5.0.2" newVersion="3.5.0.2" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" /> <bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Web.Infrastructure" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="1.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="1.0.0.0-5.2.9.0" newVersion="5.2.9.0" /> </dependentAssembly> </assemblyBinding> </runtime> <system.codedom> <compilers> <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" /> <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\"Web\" /optionInfer+" /> </compilers> </system.codedom> </configuration> <!--ProjectGuid: 75F8D488-D85A-488A-AFEB-2E93D5646800-->
06-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值