本文依赖springBoot讲解,主要讲解依赖注入的三种方式、不采用依赖注入如何获取Bean,及其springBoot获取properties文件的四种方式;本文是基础文章,不喜勿喷!!!
一、 spring依赖注入的三种方式
二、ApplicationContextAware接口
一般情况下,Spring容易使用声明是配置,只需要在web.xml中配置Listener后,该Listener就会自动初始化Spring容器,我们使用注解直接可以访问Spring中的Bean,无需访问Spring容器本身;在这种情况下,容器中的Bean处于容器的管理,我们无需主动访问Spring容器,只需要接受容器的依赖注入即可。
但是在某些特殊情况下,需要实现的功能需要开发者借助Spring容器才能实现,此时我们就要获取Spring对象;为了获取Spring容器,我们可以让Bean实现ApplicationContextAware接口。
下面的实例为实现了ApplicationContextAware接口的工具类。可以通过其类引用或这个类类型获取Spring容器中的Bean对象:
public class ApplicationUtil implements ApplicationContextAware {
// Spring 容器对象
private static ApplicationContext applicationContext;
/**
* 实现ApplicationContextAware接口, 注入Context到静态变量中.
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
ApplicationUtil.applicationContext = applicationContext;
}
/**
* 获取静态变量中的ApplicationContext.
*/
public static ApplicationContext getApplicationContext() {
assertContextInjected();
return applicationContext;
}
/**
* 从静态变量applicationContext中得到Bean, 自动转型为所赋值对象的类型.
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
assertContextInjected();
return (T) applicationContext.getBean(name);
}
/**
* 从静态变量applicationContext中得到Bean, 自动转型为所赋值对象的类型.
*/
public static <T> T getBean(Class<T> requiredType) {
assertContextInjected();
return applicationContext.getBean(requiredType);
}
/**
* 清除SpringContextHolder中的ApplicationContext为Null.
*/
public static void clearHolder() {
applicationContext = null;
}
/**
* 检查ApplicationContext不为空.
*/
private static void assertContextInjected() {
// if (applicationContext == null) {
// throw new IllegalStateException(
// "applicaitonContext未注入,请在applicationContext.xml中定义本SpringUtil--------<bean class='xxxx.SpringUtil' />");
// }
Validate.validState(applicationContext != null,
"applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringUtil.");
}
}
三、四种读取properties文件的方式
这里我们首先写一个.yml
文件:
my:
user:
name: 小明
age: 20
name: 这是地址
注意:properties
文件和yml
相同
1. @ConfigurationProperties 注解
@Component
@ConfigurationProperties("my.user")
public class User {
private String name;
private Integer age;
private String address;
// 省略getter和setter...
}
如上所示,my.user
下面的属性会自动注入到类中,我们只需要将需要将Bean
自动装载到使用的地方就可以使用了:
@RestController
public class MainController {
@Autowired
private User user;
@RequestMapping("test")
public Map<String, Object> test() {
map.put("code", "200");
map.put("msg", "添加成功");
map.put("data", user);
return map;
}
}
2.@Value("${propertyName}")注解
@RestController
public class MainController {
@Value("${my.user.name}")
private String name;
@Value("${my.user.age}")
private Integer age;
@Value("${my.user.address}")
private String address;
@RequestMapping("test")
public Map<String, Object> test() {
map.put("name", name);
map.put("age", age);
map.put("address", address);
return map;
}
}
注
:结合 @PropertySource("classpath:demo.properties")
注解,可以指定使用的properties
文件
3.Environment直接取值
@RestController
public class MainController {
@Autowired
private Environment env;
@RequestMapping("test")
public Map<String, Object> test() {
map.put("name", env.getProperty("my.user.name"););
map.put("age", env.getProperty("my.user.age"););
map.put("address", env.getProperty("my.user.address"););
return map;
}
}
使用 Environment
进行参数绑定:
// 参数注入,可使用 EnvironmentAware 注入
Environment env;
// 初始化绑定对象
Binder binder = Binder.get(context.getEnvironment());
// 实体属性绑定
BeanProperties beanProperties = binder.bind("com.bean.bind", Bindable.of(BeanProperties.class)).get();
// List属性绑定
List<BeanProperties> list = binder.bind("com.bean.bind", Bindable.listOf(BeanProperties.class)).get();
// Map属性绑定
Map<String, BeanProperties> map = binder.bind("com.bean.bind", Bindable.mapOf(String.class, BeanProperties.class)).get();
这种读取方式不支持读取其他的配置文件,如果想支持的话,可以自定义Environment
的实现类的方式实现:
public class EnvironmentPostProcessorExample implements EnvironmentPostProcessor {
private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
Resource path = new ClassPathResource("my-config.yml");
PropertySource<?> propertySource = loadYaml(path);
environment.getPropertySources().addLast(propertySource);
}
private PropertySource<?> loadYaml(Resource path) {
if (!path.exists()) {
throw new IllegalArgumentException("Resource " + path + " does not exist");
}
try {
return this.loader.load("custom-resource", path, null);
// return this.loader.load("customConfig:[classpath:/com/momo/springbootenvironment/config/config.yml]", path, null);
} catch (IOException ex) {
throw new IllegalStateException("Failed to load yaml configuration from " + path, ex);
}
}
}
注
:
- Environment已经准备好了Spring Boot默认加载的所有常用属性源。 因此,可以从环境中获取文件的位置。 此示例在属性源列表末尾添加custom-resource属性源。 可以自定义属性源的次序,如头部、某个属性源前/后、末尾等。
- 虽然在@SpringBootApplication上使用@PropertySource似乎方便又容易在环境中加载自定义资源,但Spring官方不推荐使用它,因为Spring Boot会在刷新ApplicationContext之前准备环境。 通过@PropertySource定义的任何key都加载的太晚以致于无法对自动配置产生任何影响。