本文依赖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都加载的太晚以致于无法对自动配置产生任何影响。