3.5运行时值注入

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

讨论依赖注入的时候,我们通常所讨论的是将一个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
内容概要:本文围绕EKF SLAM(扩展卡尔曼滤波同步定位与地图构建)的性能展开多项对比实验研究,重点分析在稀疏与稠密landmark环境下、预测与更新步骤同时进行与非同时进行的情况下的系统性能差异,并进一步探讨EKF SLAM在有色噪声干扰下的鲁棒性表现。实验考虑了不确定性因素的影响,旨在评估不同条件下算法的定位精度与地图构建质量,为实际应用中EKF SLAM的优化提供依据。文档还提及多智能体系统在遭受DoS攻击下的弹性控制研究,但核心内容聚焦于SLAM算法的性能测试与分析。; 适合人群:具备一定机器人学、状态估计或自动驾驶基础知识的科研人员及工程技术人员,尤其是从事SLAM算法研究或应用开发的硕士、博士研究生和相关领域研发人员。; 使用场景及目标:①用于比较EKF SLAM在不同landmark密度下的性能表现;②分析预测与更新机制同步与否对滤波器稳定性与精度的影响;③评估系统在有色噪声等非理想观测条件下的适应能力,提升实际部署中的可靠性。; 阅读建议:建议结合MATLAB仿真代码进行实验复现,重点关注状态协方差传播、观测更新频率与噪声模型设置等关键环节,深入理解EKF SLAM在复杂环境下的行为特性。稀疏 landmark 与稠密 landmark 下 EKF SLAM 性能对比实验,预测更新同时进行与非同时进行对比 EKF SLAM 性能对比实验,EKF SLAM 在有色噪声下性能实验
内容概要:本文围绕“基于主从博弈的售电商多元零售套餐设计与多级市场购电策略”展开,结合Matlab代码实现,提出了一种适用于电力市场化环境下的售电商优化决策模型。该模型采用主从博弈(Stackelberg Game)理论构建售电商与用户之间的互动关系,售电商作为领导者制定电价套餐策略,用户作为跟随者响应电价并调整用电行为。同时,模型综合考虑售电商在多级电力市场(如日前市场、实时市场)中的【顶级EI复现】基于主从博弈的售电商多元零售套餐设计与多级市场购电策略(Matlab代码实现)购电组合优化,兼顾成本最小化与收益最大化,并引入不确定性因素(如负荷波动、可再生能源出力变化)进行鲁棒或随机优化处理。文中提供了完整的Matlab仿真代码,涵盖博弈建模、优化求解(可能结合YALMIP+CPLEX/Gurobi等工具)、结果可视化等环节,具有较强的可复现性和工程应用价值。; 适合人群:具备一定电力系统基础知识、博弈论初步认知和Matlab编程能力的研究生、科研人员及电力市场从业人员,尤其适合从事电力市场运营、需求响应、售电策略研究的相关人员。; 使用场景及目标:① 掌握主从博弈在电力市场中的建模方法;② 学习售电商如何设计差异化零售套餐以引导用户用电行为;③ 实现多级市场购电成本与风险的协同优化;④ 借助Matlab代码快速复现顶级EI期刊论文成果,支撑科研项目或实际系统开发。; 阅读建议:建议读者结合提供的网盘资源下载完整代码与案例数据,按照文档目录顺序逐步学习,重点关注博弈模型的数学表达与Matlab实现逻辑,同时尝试对目标函数或约束条件进行扩展改进,以深化理解并提升科研创新能力。
使用 LLVM 获取运行时值可以通过以下几种常见方法: ### 1. 插入调试信息 在编译时插入调试信息(如 DWARF 格式),这样在运行时可以借助调试器(如 GDB)来获取值。在使用 Clang 编译时,可以通过 `-g` 选项添加调试信息。示例代码如下: ```bash clang -g -o my_program my_program.c ``` 此命令会编译 `my_program.c` 文件,并生成包含调试信息的可执行文件 `my_program`。之后可以使用 GDB 来调试该程序并获取运行时值: ```bash gdb my_program ``` 在 GDB 中,可使用 `break` 设置断点,使用 `run` 运行程序,使用 `print` 打印变量的值。 ### 2. 利用 LLVM 内联汇编 在 LLVM IR 或者 C/C++ 代码里使用内联汇编来获取运行时值。例如,在 C 代码中使用内联汇编读取寄存器的值: ```c #include <stdio.h> int main() { int value; __asm__("movl %%eax, %0" : "=r" (value)); printf("The value in EAX register is: %d\n", value); return 0; } ``` 在这个示例中,内联汇编将 EAX 寄存器的值移动到变量 `value` 中,然后打印该值。 ### 3. 自定义 LLVM 传递(Pass) 编写自定义的 LLVM 传递,在编译时插入代码以记录运行时值。首先,需要创建一个自定义的 LLVM 传递类,然后在该类的 `runOnFunction` 方法中插入代码。示例代码如下: ```cpp #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Value.h" #include "llvm/Pass.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { struct PrintValuePass : public FunctionPass { static char ID; PrintValuePass() : FunctionPass(ID) {} bool runOnFunction(Function &F) override { for (auto &BB : F) { for (auto &I : BB) { if (auto *LI = dyn_cast<LoadInst>(&I)) { Value *LoadedValue = LI->getOperand(0); errs() << "Loaded value: "; LoadedValue->print(errs()); errs() << "\n"; } } } return false; } }; } char PrintValuePass::ID = 0; static RegisterPass<PrintValuePass> X("print-value", "Print loaded values"); ``` 这个自定义传递会在编译时打印所有加载指令加载的值。可以使用以下命令运行该传递: ```bash opt -load my_pass.so -print-value my_program.bc -o my_program_opt.bc ``` ### 4. 使用 LLVM 运行时库 LLVM 有一些运行时库,像 LLVM Profiling 库,可用于收集运行时信息。在编译时链接这些库,然后在运行时获取相关的值。示例代码如下: ```bash clang -fprofile-instr-generate -fcoverage-mapping -o my_program my_program.c ./my_program llvm-profdata merge -sparse default.profraw -o default.profdata llvm-cov show my_program -instr-profile=default.profdata ``` 这些命令会编译程序,运行程序收集性能数据,合并性能数据,最后展示覆盖信息。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值