DemoApplication.java
package com.lucifer;
import com.lucifer.itheima.Component1;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.Resource;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Locale;
import java.util.Map;
@SpringBootApplication(scanBasePackages = {"com.lucifer"})
public class DemoApplication {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException {
/**
* 1.什么是BeanFactory
* 是ApplicationContext的父接口
* 是Spring的核心容器,主要的ApplicaitonContext实现都【组合】了它的功能
*
* ctrl+alt+u 查看接口的继承关系
* ctrl+f12 查看接口有哪些方法
* ctrl+v 自动生成表达式的返回值
*/
ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
// context.getBean("aaaa");
System.out.println(context);
/**
2.BeanFactory能干啥
表面上只有getBean
实际上控制反转,基本的依赖注入,直至Bean的生命周期的各种功能,都由它的实现类提供
*/
Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
singletonObjects.setAccessible(true);
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
Map<String, Object> map = (Map<String, Object>) singletonObjects.get(beanFactory);
// map.forEach((k,v)->{
// System.out.println(k + "=" +v);
// });
map.entrySet().stream().filter(e->e.getKey().startsWith("component")).forEach(e-> System.out.println(e.getKey()+ "=" +e.getValue()));
/**
* 3.ApplicationContext 比 BeanFactory多点哈
*/
/**
* 3.1国际化
*/
System.out.println(context.getMessage("hi", null, Locale.CHINA));
System.out.println(context.getMessage("hi",null,Locale.ENGLISH));
/**
* 3.2根据通配符能获取一组资源
*/
//classpath 是类路径下 file 指的是磁盘下面 classpath只是到类路径下,jar包的找不到,classpath* 能找到jar包下的
// Resource[] resources = context.getResources("classpath:application.properties");
Resource[] resources = context.getResources("classpath*:META-INF/spring.factories");
for (Resource resource:resources) {
System.out.println(resource);
}
/**
* 3.3获取一些配置信息(配置信息来自环境变量或者我们的配置文件)
*/
//environment是一些配置信息 配置信息的源可能多种多样 有的来自环境变量的键值,有的来自application.properties的键值
//不区分大小写
System.out.println(context.getEnvironment().getProperty("java_home"));
System.out.println(context.getEnvironment().getProperty("server.port"));
/**
* 3.4发布事件((发布事件的最大作用,实现组件之间的解耦)
*/
// context是事件源 也就是发布事件
// 收事件叫监听器,在spring中任何一个组件都可以作为监听器,比如我们的Component1,Component2
// 在这我们把component2作为监听器
//context.publishEvent(new UserRegisteredEvent(context));
context.getBean(Component1.class).register();
/**
* 4.学到了什么
* a. BeanFactory 与 ApplicationContext 并不仅仅是简单接口继承的关系,ApplicaitonContext组合并扩展了BeanFactory的功能
* b. 学到了一种新的代码之间解耦(aop也可以)途径(事件发布)
*/
}
}
Component1.java
package com.lucifer.itheima;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class Component1 {
@Autowired
private ApplicationEventPublisher context;
public void register() {
log.info("用户注册");
context.publishEvent(new UserRegisteredEvent(this));
}
}
Component2.java
package com.lucifer.itheima;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class Component2 {
@EventListener
public void aaa(UserRegisteredEvent event) {
log.info("{}",event);
log.info("发送短信");
}
}
UserRegisteredEvent.java
package com.lucifer.itheima;
import org.springframework.context.ApplicationEvent;
public class UserRegisteredEvent extends ApplicationEvent {
//source代表事件的事件源,也就是谁发的这个事件
public UserRegisteredEvent(Object source) {
super(source);
}
}
Resource Bundle 'message’目录下
message_en.properties
hi=hello
message_zh.properties
hi=你好