Spring BeanFactory和ApplicationContext BeanFactory 1 2 3 4 5 6 7 8 9 10 @SpringBootApplication public class SpringDemoTestApplication { public static void main (String[] args) { ConfigurableApplicationContext context = SpringApplication.run(SpringDemoTestApplication.class, args); } }
打开类图 我们可以发现:
BeanFactory
是ApplicationContext
的父接口,是Spring
的核心容器 ,主要的ApplicationContext
继承实现 并组合 了它的方法
1 2 context.getContext("name" );
通过调试可以发现ApplicationContext
里面包含BeanFactory
对象
BeanFactory功能
BeanFactory看似只有声明了这些接口,但是它的实现类提供了控制反转,依赖注入、Bean的声明周期的各种功能
查看BeanFactory
的一个实现类DefaultSingletonBeanRegistry
,可以发现只是它组合了其他的父类
查看其中的一个父类 DefaultSingletonBeanRegistry
,它管理类所有的单例对象
通过 反射 获取 DefaultSingletonBeanRegistry
类中成员属性 singletonObjects
1 2 3 4 5 6 Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects" ); singletonObjects.setAccessible(true ); ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); Map<String, Object> map = (Map<String, Object>) singletonObjects.get(beanFactory); map.entrySet().stream().forEach(stringObjectEntry -> System.out.println(stringObjectEntry.getKey() + "=>" + stringObjectEntry.getValue()));
ApplicationContext ApplicationContext
的扩展功能主要继承于MessageSource
,ResourcePatternResolver
,ApplicationEventPublisher
,EnvironmentCapable
这些父接口
MessageSource 1 context.getMessage("hi" ,null , Locale.CHINA)
ResourcePatternResolver 1 2 Resource resource = context.getResource("classpath:application.properties" );Resource[] resources = context.getResources("classpath*:META-INF/spring.factories" );
EnvironmentCapable
1 2 String property = context.getEnvironment().getProperty("server.port" );
ApplicationEventPublisher 声明事件 1 2 3 4 5 6 7 8 9 10 public class DemoEvent extends ApplicationEvent { public DemoEvent (Object source) { super (source); } }
事件监听 1 2 3 4 5 6 7 8 9 10 11 12 13 @Component public class Subscribe { Logger logger = LoggerFactory.getLogger(Subscribe.class); @EventListener public void subscribe (DemoEvent demoEvent) { logger.info("demoEvent:" + demoEvent); } }
发送事件 1 2 3 4 5 6 7 8 9 10 11 @Component public class Publish { Logger logger = LoggerFactory.getLogger(Publish.class); @Resource private ApplicationEventPublisher applicationEventPublisher; public void publish () { applicationEventPublisher.publishEvent(new DemoEvent (applicationEventPublisher)); } }
执行发送 1 2 3 context.getBean(Publish.class).publish();
总结
BeanFactory
与 ApplicationContext
不仅仅是简单接口的继承关系,ApplicationContext
组合并通过继承其他父类扩展了BeanFactory
的功能
BeanFactory BeanFactory的实现 首先,我们手动注册配置类定义信息 和常见的后处理器 ,手动生成BeanFactory
,添加后处理器并执行它们
我们查看BeanFactory
一个默认的常见实现DefaultListableBeanFactory
:
1 2 DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory ();
创建Bean对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public class Bean1 { private Logger logger = LoggerFactory.getLogger(Bean1.class); public Bean1 () { logger.info("构造 Bean1" ); } @Resource private Bean2 bean2; public Bean2 getBean2 () { return bean2; } } public class Bean2 { private Logger logger = LoggerFactory.getLogger(Bean2.class); public Bean2 () { logger.info("构造 Bean2" ); } } @Configuration public class Config { @Bean public Bean1 bean1 () { return new Bean1 (); } @Bean public Bean2 bean2 () { return new Bean2 (); } }
通过 BeanDefinition
定义Bean并注册到BeanFactory
里
BeanDefinition描述一个bean实例,该实例具有属性值、构造函数参数值以及由具体实现提供的进一步信息
1 2 3 4 AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class) .setScope(ConfigurableBeanFactory.SCOPE_SINGLETON).getBeanDefinition();
1 2 beanFactory.registerBeanDefinition("config" , beanDefinition);
1 2 3 4 5 6 beanFactory.registerBeanDefinition("config" , beanDefinition);
注册后置处理器到 BeanFactory
1 2 AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
执行BeanFactory
指定后处理器
1 2 3 4 Map<String, BeanFactoryPostProcessor> beansOfType = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class); beansOfType.values().stream().forEach(beanFactoryPostProcessor -> beanFactoryPostProcessor.postProcessBeanFactory(beanFactory));
获取依赖注入的Bean
:查看 Bean1
中注入的 Bean2
对象,发现依赖注入并没有成功
1 2 logger.info("Bean1 中注入的 Bean2 对象:{}" , beanFactory.getBean(Bean1.class).getBean2());
开启Bean后处理器,发现成功获取依赖注入的对象,但是对象是 懒汉式 的方式创建的
1 2 3 4 5 beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor); logger.info("Bean1 中注入的 Bean2 对象:{}" , beanFactory.getBean(Bean1.class).getBean2());
打开 AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory)
方法,可以发现 后处理器
注册了 @Autowired
和 @Resource
的处理器
可以通过BeanFactory的方法提前初始化所有的单例Bean
1 2 beanFactory.preInstantiateSingletons();
BeanFactory不会主动调用BeanFactory
后处理器,不会添加Bean
后处理器,不会主动初始化单例Bean,而是由ApplicationContext
调用
定义接口 创建两个类实现同一接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public interface Inter {} public class Bean3 implements Inter { private Logger logger = LoggerFactory.getLogger(Bean3.class); public Bean3 () { logger.info("构造 Bean3" ); } } public class Bean4 implements Inter { private Logger logger = LoggerFactory.getLogger(Bean4.class); public Bean4 () { logger.info("构造 Bean4" ); } }
在Bean
中使用 @Autowired
依赖注入Inter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Bean1 { private Logger logger = LoggerFactory.getLogger(Bean1.class); public Bean1 () { logger.info("构造 Bean1" ); } @Autowired private Bean2 bean2; public Bean2 getBean2 () { return bean2; } @Autowired private Inter inter; public Inter getinter () { return inter; } }
@Autowire
注解默认通过 ByType
方式注入,ByType
方式没有找到再去根据 ByName
方式寻找
1 2 3 4 5 6 @Autowired private Inter bean3;public Inter getBean3 () { return bean3; }
@Resource
优先根据ByName
方式注入,默认情况下要求被注入的Bean必须存在,注解里name属性的优先级高于成员变量Name
1 2 3 4 5 6 @Resource(name = "bean4") private Inter bean3;public Inter getBean3 () { return bean3; }
如果 @Resource
和 @Autowired
的同时存在,优先注入 @Autowired
如果使用 依赖比较器
进行 排序 会发现 @Autowired
先生效,这是因为 两个后置处理器 的 order
值不一样,值越小的优先级越高
1 2 3 4 5 beanFactory.getBeansOfType(BeanPostProcessor.class).values() .stream() .sorted(beanFactory.getDependencyComparator()) .forEach(beanFactory::addBeanPostProcessor);
ApplicationContext常见实现和用法 常见实现 ClassPathXmlApplication
基于 classpath
下 xml
格式配置文件来创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class Bean5 { private Logger logger = LoggerFactory.getLogger(Bean5.class); private Bean6 bean6; public Bean5 () { logger.info("构造 Bean5" ); } public void setBean6 (Bean6 bean6) { this .bean6 = bean6; } public Bean6 getBean6 () { return bean6; } }
1 2 3 4 5 6 7 public class Bean6 { private Logger logger = LoggerFactory.getLogger(Bean6.class); public Bean6 () { logger.info("构造 Bean6" ); } }
1 2 3 4 5 6 7 8 9 <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" > <bean id ="bean5" class ="com.example.demo.bean.Bean5" > <property name ="bean6" ref ="bean6" > </property > </bean > <bean id ="bean6" class ="com.example.demo.bean.Bean6" /> </beans >
1 2 3 4 5 6 7 8 9 @Test public void testClass () { ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext ("test.xml" ); logger.info("查看 classPathXmlApplicationContext 中所有的容器" ); Arrays.stream(classPathXmlApplicationContext.getBeanDefinitionNames()) .forEach(s -> logger.info(s)); logger.info("查看是否依赖注入是否成功:{}" , classPathXmlApplicationContext.getBean(Bean5.class).getBean6()); }
它的底层原理就是通过 XmlBeanDefinitionReader
加载配置文件 读取 bean
的定义至 beanFactory
1 2 3 4 5 6 7 8 DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory ();XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader (beanFactory);reader.loadBeanDefinitions(new ClassPathResource ("test.xml" )); logger.info("查看 classPathXmlApplicationContext 中所有的容器" ); Arrays.stream(beanFactory.getBeanDefinitionNames()) .forEach(s -> logger.info(s)); logger.info("查看是否依赖注入是否成功:{}" , beanFactory.getBean(Bean5.class).getBean6());
FileSystemXmlApplicationContext
基于 磁盘
路径下的 xml 格式的配置文件来创建
1 2 3 4 5 6 7 8 9 @Test public void testFileSystemXmlApplicationContext () { FileSystemXmlApplicationContext fileSystemXmlApplicationContext = new FileSystemXmlApplicationContext ("src/main/resources/test.xml" ); logger.info("查看 classPathXmlApplicationContext 中所有的容器" ); Arrays.stream(fileSystemXmlApplicationContext.getBeanDefinitionNames()) .forEach(s -> logger.info(s)); logger.info("查看是否依赖注入是否成功:{}" , fileSystemXmlApplicationContext.getBean(Bean5.class).getBean6()); }
AnnotationConfigServletWebApplicationContext
基于 注解配置类
来创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Configuration public class BeanConfig { @Bean public Bean5 bean5 (Bean6 bean6) { Bean5 bean5 = new Bean5 (); bean5.setBean6(bean6); return bean5; } @Bean public Bean6 bean6 () { return new Bean6 (); } }
1 2 3 4 5 6 7 8 9 10 @Test public void testAnnotationConfigApplicationContext () { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext (BeanConfig.class); logger.info("查看 classPathXmlApplicationContext 中所有的容器" ); Arrays.stream(annotationConfigApplicationContext.getBeanDefinitionNames()) .forEach(s -> logger.info(s)); logger.info("查看是否依赖注入是否成功:{}" , annotationConfigApplicationContext.getBean(Bean5.class).getBean6()); }
AnnotationConfigServletWebApplicationContext
基于 注解配置类
来创建,用于web环境
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 @Configuration public class WebConfig { @Bean public ServletWebServerFactory servletWebServerFactory () { return new TomcatServletWebServerFactory (); } @Bean public DispatcherServlet dispatcherServlet () { return new DispatcherServlet (); } @Bean @Primary public DispatcherServletRegistrationBean dispatcherServletRegistrationBean (DispatcherServlet dispatcherServlet) { return new DispatcherServletRegistrationBean (dispatcherServlet, "/" ); } @Bean("/hello") public Controller controller () { return (request, response) -> { response.getWriter().write("Hello world!" ); return null ; }; } }
1 2 3 4 5 6 7 8 s @Test public void testAnnotationConfigServletWebApplicationContext () { AnnotationConfigServletWebApplicationContext annotationConfigServletWebApplicationContext = new AnnotationConfigServletWebApplicationContext (WebConfig.class); logger.info("查看 classPathXmlApplicationContext 中所有的容器" ); Arrays.stream(annotationConfigServletWebApplicationContext.getBeanDefinitionNames()) .forEach(s -> logger.info(s)); }
Bean的生命周期 SpringBean的生命周期的各个阶段 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Component public class LifeCycleBean { private static final Logger logger = LoggerFactory.getLogger(LifeCycleBean.class); public LifeCycleBean () { logger.debug("构造:LifeCycleBean" ); } @Autowired public void autowired (@Value("${server.port}") String port) { logger.debug("LifeCycleBean依赖注入:{}" , port); } @PostConstruct public void init () { logger.debug("初始化:LifeCycleBean" ); } @PreDestroy public void destroy () { logger.debug("销毁:LifeCycleBean" ); } }
1 2 ConfigurableApplicationContext context = SpringApplication.run(SpringDemoTestApplication.class, args);context.close();
Bean 的生命周期:构造->依赖注入->初始化->销毁
添加一些 自定义 Bean 的后处理器
,对于Bean的生命周期进行增强,完成生命周期的扩展
需要实现 InstantiationAwareBeanPostProcessor
和 DestructionAwareBeanPostProcessor
接口,这两个接口都继承于BeanPostProcessor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 @Component public class CustomBeanPostProcessor implements InstantiationAwareBeanPostProcessor , DestructionAwareBeanPostProcessor { private static final Logger logger = LoggerFactory.getLogger(CustomBeanPostProcessor.class); @Override public Object postProcessBeforeInstantiation (Class<?> beanClass, String beanName) throws BeansException { if (beanName.equals("lifeCycleBean" )) { logger.debug(">>>>实例化之前执行<<<<" ); } return null ; } @Override public boolean postProcessAfterInstantiation (Object bean, String beanName) throws BeansException { if (beanName.equals("lifeCycleBean" )) { logger.debug(">>>>实例化之后执行<<<<" ); } return true ; } @Override public PropertyValues postProcessProperties (PropertyValues pvs, Object bean, String beanName) throws BeansException { if (beanName.equals("lifeCycleBean" )) { logger.debug(">>>>依赖注入阶段执行<<<<" ); } return pvs; } @Override public Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException { if (beanName.equals("lifeCycleBean" )) { logger.debug(">>>>初始化之前执行 <<<<" ); } return bean; } @Override public Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException { if (beanName.equals("lifeCycleBean" )) { logger.debug(">>>>初始化之后执行 <<<<" ); } return bean; } @Override public void postProcessBeforeDestruction (Object bean, String beanName) throws BeansException { if (beanName.equals("lifeCycleBean" )) { logger.debug(">>>>销毁之前执行方法<<<<" ); } } }
模版设计模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class DemoBeanFactory { private static final Logger logger = LoggerFactory.getLogger(DemoBeanFactory.class); public Object createBean () { Object bean = new Object (); logger.info("构造 Bean" ); logger.info("依赖注入 Bean" ); for (BeanPostProcessor postProcessor : postProcessors) { postProcessor.inject(bean); } logger.info("初始化 Bean" ); return bean; } private List<BeanPostProcessor> postProcessors = new ArrayList <>(); public void addBeanPostProcessor (BeanPostProcessor beanPostProcessor) { postProcessors.add(beanPostProcessor); } public interface BeanPostProcessor { void inject (Object bean) ; } }
1 2 3 4 5 6 7 @Test public void testTemplate () { DemoBeanFactory demoBeanFactory = new DemoBeanFactory (); demoBeanFactory.addBeanPostProcessor(bean -> logger.info("后处理器1" )); demoBeanFactory.addBeanPostProcessor(bean -> logger.info("后处理器2" )); demoBeanFactory.createBean(); }
Bean后处理器 Bean后处理器作用
Bean后处理器
是 为Bean生命周期
各个阶段
提供扩展功能
用 GenericApplicationContext
探究一下 一些注解 分别由哪些处理器来解析的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 public class BeanReplica1 { private static final Logger logger = LoggerFactory.getLogger(BeanReplica1.class); private BeanReplica2 beanReplica2; private BeanReplica3 beanReplica3; private String port; @Autowired public void setBeanReplica2 (BeanReplica2 beanReplica2) { logger.info("@Autowired生效:{}" , beanReplica2); this .beanReplica2 = beanReplica2; } @Resource public void setBeanReplica3 (BeanReplica3 beanReplica3) { logger.info("@Resource生效:{}" , beanReplica3); this .beanReplica3 = beanReplica3; } @Autowired public void setPort (@Value("${server.port}") String port) { logger.info("@Resource生效:{}" , beanReplica3); this .port = port; } @PostConstruct public void init () { logger.info("@PostConstruct生效" ); } @PreDestroy public void destroy () { logger.info("@PreDestroy生效" ); } } public class BeanReplica2 {} public class BeanReplica3 {}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Test public void testGenericApplicationContext () { GenericApplicationContext genericApplicationContext = new GenericApplicationContext (); genericApplicationContext.registerBean("beanReplica1" , BeanReplica1.class); genericApplicationContext.registerBean("beanReplica2" , BeanReplica2.class); genericApplicationContext.registerBean("beanReplica3" , BeanReplica3.class); genericApplicationContext.refresh(); Arrays.stream(genericApplicationContext.getBeanDefinitionNames()).forEach(System.out::println); genericApplicationContext.close(); }
在未添加后处理器的容器里 ,只注册了三个Bean实例
1 2 3 4 5 @Data @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true) public class Prop { private String port; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 @Test public void testGenericApplicationContext () { GenericApplicationContext genericApplicationContext = new GenericApplicationContext (); genericApplicationContext.registerBean("beanReplica1" , BeanReplica1.class); genericApplicationContext.registerBean("beanReplica2" , BeanReplica2.class); genericApplicationContext.registerBean("beanReplica3" , BeanReplica3.class); genericApplicationContext.registerBean("prop" , Prop.class); genericApplicationContext.getDefaultListableBeanFactory() .setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver ()); genericApplicationContext.registerBean(AutowiredAnnotationBeanPostProcessor.class); genericApplicationContext.registerBean(CommonAnnotationBeanPostProcessor.class); ConfigurationPropertiesBindingPostProcessor.register(genericApplicationContext.getDefaultListableBeanFactory()); genericApplicationContext.refresh(); Arrays.stream(genericApplicationContext.getBeanDefinitionNames()).forEach(System.out::println); System.out.println(genericApplicationContext.getBean(Prop.class)); genericApplicationContext.close(); }
常见的后处理器 AutowiredAnnotationBeanPostProcessor 运行分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 @Test public void testAutowiredAnnotationBeanPostProcessor () { DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory (); beanFactory.registerSingleton("beanReplica2" , new BeanReplica2 ()); beanFactory.registerSingleton("beanReplica3" , new BeanReplica3 ()); beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver ()); beanFactory.addEmbeddedValueResolver(new StandardEnvironment ()::resolvePlaceholders); AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor (); autowiredAnnotationBeanPostProcessor.setBeanFactory(beanFactory); BeanReplica1 beanReplica1 = new BeanReplica1 (); logger.info("beanReplica1:{}" , beanReplica1.toString()); autowiredAnnotationBeanPostProcessor.postProcessProperties(null , beanReplica1, "beanReplica1" ); logger.info("bean1:{}" , beanReplica1.toString()); }
autowiredAnnotationBeanPostProcessor.postProcessProperties的执行过程 点击 进入 autowiredAnnotationBeanPostProcessor.postProcessProperties
方法,发现里面第一步获取 @Autowired 和 @Value 注解的 成员变量 和 方法参数信息 的 InjectionMetadata
对象信息。我们可以通过 反射
获取 其中的信息
1 2 3 4 5 6 7 8 9 10 Method findAutowiringMetadata = autowiredAnnotationBeanPostProcessor.getClass() .getDeclaredMethod("findAutowiringMetadata" , String.class, Class.class, PropertyValues.class); findAutowiringMetadata.setAccessible(true ); InjectionMetadata metadata = (InjectionMetadata) findAutowiringMetadata.invoke(autowiredAnnotationBeanPostProcessor, "beanReplica1" , BeanReplica1.class, null ); logger.info("metadata: {}" , metadata);
调用 InjectionMetadata.inject
进行 依赖 注入
1 2 metadata.inject(beanReplica1, "beanReplica1" , null );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 @Test public void testDoResolveDependency () throws Throwable { DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory (); beanFactory.registerSingleton("beanReplica2" , new BeanReplica2 ()); beanFactory.registerSingleton("beanReplica3" , new BeanReplica3 ()); beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver ()); beanFactory.addEmbeddedValueResolver(new StandardEnvironment ()::resolvePlaceholders); AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor (); autowiredAnnotationBeanPostProcessor.setBeanFactory(beanFactory); BeanReplica1 beanReplica1 = new BeanReplica1 (); logger.info("beanReplica1:{}" , beanReplica1.toString()); Field fieldBeanReplica3 = BeanReplica1.class.getDeclaredField("beanReplica3" ); DependencyDescriptor descriptorForBean3 = new DependencyDescriptor (fieldBeanReplica3, false ); BeanReplica3 beanReplica3 = (BeanReplica3) beanFactory.doResolveDependency(descriptorForBean3, null , null , null ); logger.info("beanReplica3--->{}" , beanReplica3); Method setBeanReplica2 = BeanReplica1.class.getDeclaredMethod("setBeanReplica2" , BeanReplica2.class); DependencyDescriptor descriptorForBean2 = new DependencyDescriptor (new MethodParameter (setBeanReplica2, 0 ), false ); BeanReplica2 beanReplica2 = (BeanReplica2) beanFactory.doResolveDependency(descriptorForBean2, null , null , null ); logger.info("beanReplica2---->{}" , beanReplica2); Method setPort = beanReplica1.getClass().getDeclaredMethod("setPort" , String.class); DependencyDescriptor descriptorForString = new DependencyDescriptor (new MethodParameter (setPort, 0 ), false ); String port = (String) beanFactory.doResolveDependency(descriptorForString, null , null , null ); logger.info("port---->{}" , port); beanReplica1.setBeanReplica2(beanReplica2); beanReplica1.setBeanReplica3(beanReplica3); beanReplica1.setPort(port); logger.info("bean1:{}" , beanReplica1.toString()); }
BeanFactory后处理器 BeanFactory后处理器的作用
BeanFactory后处理器
的作用:为 BeanFatory
提供扩展,补充 Bean的定义
常见的BeanFactory后处理器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @Test public void testBeanFactoryPostProcessor () { GenericApplicationContext genericApplicationContext = new GenericApplicationContext (); genericApplicationContext.registerBean("config1" , Config1.class); genericApplicationContext.registerBean(ConfigurationClassPostProcessor.class); genericApplicationContext.registerBean( MapperScannerConfigurer.class, db -> { db.getPropertyValues().add("basePackage" , "com.example.demo.mapper" ); } ); genericApplicationContext.refresh(); Arrays.stream(genericApplicationContext.getBeanDefinitionNames()).forEach(System.out::println); genericApplicationContext.destroy(); }
BeanFactory后置处理器实现 @Component 简单实现 将 类上有 @Component
注解的注入到容器中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 @Test public void testBeanFactoryPostProcessorDemo () throws IOException { GenericApplicationContext genericApplicationContext = new GenericApplicationContext (); genericApplicationContext.registerBean("config1" , Config1.class); ComponentScan componentScan = AnnotationUtils.findAnnotation(Config1.class, ComponentScan.class); if (componentScan != null ) { for (String s : componentScan.basePackages()) { String path = "classpath*:" + s.replace("." , "/" ) + "/**/*.class" ; Resource[] resources = genericApplicationContext.getResources(path); CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory (); AnnotationBeanNameGenerator annotationBeanNameGenerator = new AnnotationBeanNameGenerator (); for (Resource resource : resources) { MetadataReader metadataReader = factory.getMetadataReader(resource); AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); logger.info( "类名:{}, 类上是否存在 @Component 注解:{}, 类上是否存在 @Component派生 注解:{} " , metadataReader.getClassMetadata().getClassName(), metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName()), metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()) ); if (annotationMetadata.hasAnnotation(Component.class.getName()) || annotationMetadata.hasMetaAnnotation(Component.class.getName())) { AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(metadataReader.getClassMetadata().getClassName()).getBeanDefinition(); String beanName = annotationBeanNameGenerator.generateBeanName(beanDefinition, genericApplicationContext.getDefaultListableBeanFactory()); genericApplicationContext.registerBeanDefinition(beanName, beanDefinition); } } } genericApplicationContext.refresh(); Arrays.stream(genericApplicationContext.getBeanDefinitionNames()).forEach(System.out::println); genericApplicationContext.destroy(); } }
BeanFactoryPostProcessor 通过 实现BeanFactory
后置处理器接口,将 类上有 @Component
注解的注入到容器中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 public class ComponentScanPostProcessor implements BeanDefinitionRegistryPostProcessor { private static final Logger logger = LoggerFactory.getLogger(ComponentScanPostProcessor.class); @Override public void postProcessBeanFactory (ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { } @Override @SneakyThrows public void postProcessBeanDefinitionRegistry (BeanDefinitionRegistry beanFactory) throws BeansException { ComponentScan componentScan = AnnotationUtils.findAnnotation(Config1.class, ComponentScan.class); if (componentScan != null ) { for (String s : componentScan.basePackages()) { String path = "classpath*:" + s.replace("." , "/" ) + "/**/*.class" ; Resource[] resources = new PathMatchingResourcePatternResolver ().getResources(path); CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory (); AnnotationBeanNameGenerator annotationBeanNameGenerator = new AnnotationBeanNameGenerator (); for (Resource resource : resources) { MetadataReader metadataReader = factory.getMetadataReader(resource); AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); logger.info( "类名:{}, 类上是否存在 @Component 注解:{}, 类上是否存在 @Component派生 注解:{} " , metadataReader.getClassMetadata().getClassName(), metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName()), metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()) ); if (annotationMetadata.hasAnnotation(Component.class.getName()) || annotationMetadata.hasMetaAnnotation(Component.class.getName())) { AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(metadataReader.getClassMetadata().getClassName()) .getBeanDefinition(); String beanName = annotationBeanNameGenerator.generateBeanName(beanDefinition, beanFactory); beanFactory.registerBeanDefinition(beanName, beanDefinition); } } } } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @Test public void testBeanFactoryComponentPostProcessor () { GenericApplicationContext genericApplicationContext = new GenericApplicationContext (); genericApplicationContext.registerBean("config1" , Config1.class); genericApplicationContext.registerBean(ConfigurationClassPostProcessor.class); genericApplicationContext.registerBean( MapperScannerConfigurer.class, db -> { db.getPropertyValues().add("basePackage" , "com.example.demo.mapper" ); } ); genericApplicationContext.refresh(); Arrays.stream(genericApplicationContext.getBeanDefinitionNames()).forEach(System.out::println); genericApplicationContext.destroy(); }
@Bean 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public class BeanPostProcessor implements BeanDefinitionRegistryPostProcessor { private static final Logger logger = LoggerFactory.getLogger(BeanPostProcessor.class); @Override public void postProcessBeanFactory (ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { } @Override @SneakyThrows public void postProcessBeanDefinitionRegistry (BeanDefinitionRegistry beanFactory) throws BeansException { CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory (); MetadataReader metadataReader = factory.getMetadataReader(new ClassPathResource ("com/example/demo/config/config1.class" )); Set<MethodMetadata> annotatedMethods = metadataReader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName()); annotatedMethods.forEach(method -> { String initMethod = (String) method.getAnnotationAttributes(Bean.class.getName()).get("initMethod" ); AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition() .setFactoryMethodOnBean(method.getMethodName(), "config1" ) .setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR) .setInitMethodName(initMethod.length() > 0 ? initMethod : null ) .getBeanDefinition(); beanFactory.registerBeanDefinition(method.getMethodName(), beanDefinition); }); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Test public void testBeanFactoryBeanPostProcessor () { GenericApplicationContext genericApplicationContext = new GenericApplicationContext (); genericApplicationContext.registerBean("config1" , Config1.class); genericApplicationContext.addBeanFactoryPostProcessor(new ComponentScanPostProcessor ()); genericApplicationContext.addBeanFactoryPostProcessor(new BeanPostProcessor ()); genericApplicationContext.refresh(); Arrays.stream(genericApplicationContext.getBeanDefinitionNames()).forEach(System.out::println); genericApplicationContext.destroy(); }
@Mapper 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class MapperPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory) throws BeansException { } @Override @SneakyThrows public void postProcessBeanDefinitionRegistry (BeanDefinitionRegistry beanFactory) throws BeansException { PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver (); Resource[] resources = resolver.getResources("classpath:com/example/demo/mapper/**/*.class" ); CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory (); AnnotationBeanNameGenerator annotationBeanNameGenerator = new AnnotationBeanNameGenerator (); for (Resource resource : resources) { MetadataReader metadataReader = factory.getMetadataReader(resource); if (metadataReader.getClassMetadata().isInterface()) { AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class) .addConstructorArgValue(metadataReader.getClassMetadata().getClassName()) .setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE) .getBeanDefinition(); String beanName = annotationBeanNameGenerator.generateBeanName( BeanDefinitionBuilder.genericBeanDefinition(metadataReader.getClassMetadata().getClassName()).getBeanDefinition(), beanFactory ); beanFactory.registerBeanDefinition(beanName, beanDefinition); } } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Test public void testMapperFactoryBeanPostProcessor () { GenericApplicationContext genericApplicationContext = new GenericApplicationContext (); genericApplicationContext.registerBean("config1" , Config1.class); genericApplicationContext.addBeanFactoryPostProcessor(new ComponentScanPostProcessor ()); genericApplicationContext.addBeanFactoryPostProcessor(new BeanPostProcessor ()); genericApplicationContext.addBeanFactoryPostProcessor(new MapperPostProcessor ()); genericApplicationContext.refresh(); Arrays.stream(genericApplicationContext.getBeanDefinitionNames()).forEach(System.out::println); genericApplicationContext.destroy(); }
Aware和InitalizingBean
Aware 接口用于 注入 一些与容器相关信息:提供了一种内置的注入手段,可以注入BeanFactory
、ApplicationContext
等,Aware接口属于内置功能,不加任何的扩展即可使用,不存在失效的情况
InitalizingBean接口提供一种内置的初始化方法
内置的注入和初始化不受扩展功能的影响,总会被执行,因此Spring框架内部常用它们
BeanNameAware
:注入 Bean名称
BeanFactoryAware
:注入 BeanFactory
容器
ApplicationContextAware
:注入 ApplicationContext
容器
EmbeddedValueResolverAware
:注入 单个属性值 ${}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class MyBean implements BeanNameAware , ApplicationContextAware, InitializingBean { private static final Logger logger = LoggerFactory.getLogger(MyBean.class); @Override public void setBeanName (String name) { logger.info("beanName:{}" , name); } @Override public void setApplicationContext (ApplicationContext applicationContext) throws BeansException { logger.info("applicationContext:{}" , applicationContext); } @Override public void afterPropertiesSet () throws Exception { logger.info("initializingBean" ); } }
初始化和销毁 Spring提供了多种初始化和销毁的手段,它们有固定的执行顺序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public class CustomBean implements InitializingBean , DisposableBean { private static final Logger logger = LoggerFactory.getLogger(CustomBean.class); @PostConstruct public void init () { logger.info(" @PostConstruct 初始化" ); } @Override public void afterPropertiesSet () throws Exception { logger.info(" InitializingBean接口 初始化" ); } public void initMethod () { logger.info(" initMethod 初始化" ); } @PreDestroy public void close () { logger.info(" @PreDestroy 销毁" ); } public void disposeMethod () { logger.info(" disposeMethod 销毁" ); } @Override public void destroy () throws Exception { logger.info(" DisposableBean接口 销毁" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @SpringBootApplication public class SpringDemoTestApplication { public static void main (String[] args) throws NoSuchFieldException, IllegalAccessException, IOException { Logger logger = LoggerFactory.getLogger(SpringDemoTestApplication.class); ConfigurableApplicationContext context = SpringApplication.run(SpringDemoTestApplication.class, args); context.close(); } @Bean(initMethod = "initMethod", destroyMethod = "disposeMethod") public CustomBean customBean () { return new CustomBean (); }
初始化:@PostConstruct -> InitializingBean 接口方法 -> @Bean属性值initMethod
销毁:@PreDestory -> DisposableBean 接口方法 -> @Bean属性值 disposeMethod
Scope Scope 类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS) @Component public class BeanForRequest implements InitializingBean , DisposableBean { private static final Logger logger = LoggerFactory.getLogger(BeanForRequest.class); @Override public void destroy () throws Exception { logger.info("销毁 BeanForRequest" ); } @Override public void afterPropertiesSet () throws Exception { logger.info("初始化 BeanForRequest" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Scope(value = WebApplicationContext.SCOPE_APPLICATION, proxyMode = ScopedProxyMode.TARGET_CLASS) @Component public class BeanForApplication implements InitializingBean , DisposableBean { private static final Logger logger = LoggerFactory.getLogger(BeanForApplication.class); @Override public void destroy () throws Exception { logger.info("销毁 BeanForApplication" ); } @Override public void afterPropertiesSet () throws Exception { logger.info("初始化 BeanForApplication" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS) @Component public class BeanForSession implements InitializingBean , DisposableBean { private static final Logger logger = LoggerFactory.getLogger(BeanForSession.class); @Override public void destroy () throws Exception { logger.info("销毁 BeanForSession" ); } @Override public void afterPropertiesSet () throws Exception { logger.info("初始化 BeanForSession" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @RestController(value = "/scope") public class ScopeController { @Lazy @Resource private BeanForApplication beanForApplication; @Lazy @Resource private BeanForRequest beanForRequest; @Lazy @Resource private BeanForSession beanForSession; @GetMapping("/test") public String test () { StringBuilder sb = new StringBuilder (); return sb.append("beanForRequest:" + beanForRequest).append("\n" ) .append("beanForSession:" + beanForSession).append("\n" ) .append("beanForApplication:" + beanForApplication).append("\n" ) .toString(); } }
每次 HTTP 请求会产生一个新的 Bean,并在请求结束后销毁
使用不同的浏览器维护着不同的 Session,因此使用不同的浏览器会产生不同的 BeanForSession 对象,该 Bean 在当前 HTTP Session 内有效,Session 过期后被销毁
每个 Web 应用启动时创建一个 Bean 对象,该 Bean 在当前Serlvet Tomcat应用启动时间内有效
Scope 失效分析 1 2 3 4 @Component @Scope(value = SCOPE_PROTOTYPE) public class F1 {}
1 2 3 4 5 6 7 8 9 @Component public class E { @Resource private F1 f1; public F1 getF1 () { return f1; } }
1 2 3 4 5 6 7 8 9 10 11 12 @SpringBootApplication public class SpringDemoTestApplication { public static void main (String[] args) throws NoSuchFieldException, IllegalAccessException, IOException { Logger logger = LoggerFactory.getLogger(SpringDemoTestApplication.class); ConfigurableApplicationContext context = SpringApplication.run(SpringDemoTestApplication.class, args); E bean = context.getBean(E.class); logger.info("{}" , bean.getF1()); logger.info("{}" , bean.getF1()); logger.info("{}" , bean.getF1()); } }
单例注入多例,Scoep 失效情况
对于 单列对象,依赖注入仅仅发生了一次,没有用到多例的F,因此 E 用的始终是第一次依赖注入的 F
解决方式:
代理对象是同一个,但是每次使用代理对象任意方法时,有代理创建新的对象
注入 ObjectFactory 工厂,从中获取多例对象
注入 ApplicationContext 工厂,从中获取多例对象
解决方法不同,但是原理一致,都是通过代理对象
或者工厂
推迟其他scope bean的获取