- InitializingBean接口
这个接口就这一个方法,这个接口在一些中间件中肯定会涉及到,因为它独特的魅力,首先看它bean实例化执行的位置:package org.springframework.beans.factory; public interface InitializingBean { void afterPropertiesSet() throws Exception; }
一般什么时候需要用到实现这个接口呢?当你需要给bean的属性设置值,是不是感觉等于没说?这么说吧:写代码的时候可以利用这一个方法,来触发一些任务,例如,轮询数据库获取数据;初始化一些参数;触发一些周期性事件等。特别地,当项目中需要从数据库中获取不变配置项,可以利用该方法只在Java Bean启动的时候调用的特性,减少对数据库的访问量。
- Aware接口
比如用的最多的:ApplicationContextAware、BeanFactoryAware、XXXAware......
一般什么时候需要用到实现这个接口呢?当你的bean希望能持有XXX作为属性的时候,你就实现XXXAware,比如你想在Bean中定义一个ApplicationContext对象,你需要初始化它,那么就可以实现ApplicationContextAware,在Spring容器加载Bean的过程中,就会调用:如下示例,实现ApplicationContextAware接口的setApplicationContext方法,Spring容器会在适当的适合调用这个setApplicationContext方法,将ApplicationContext的引用传递给下面定义的ApplicationContextHolder的applicationContext属性。XXXAware什么时候触发执行呢》参考上面的图吧,图的左边:检测Aware相关接口并.......import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class ApplicationContextHolder implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { ApplicationContextHolder.applicationContext = applicationContext; } public static ApplicationContext getApplicationContext() { return applicationContext; } }
- FactoryBean接口
一般什么时候需要用到实现这个接口呢?FactoryBean接口的核心就在于通过getObject方法可以获取的是它所生产的对象,所以我们在Proxy创建代理对象的时候就比较方便。还有一些bean,如果通过配置的方式,会显得比较麻烦和复杂,那么这时候适当的采用编码方式在某些场合下还是挺不错的Spring容器默认加载bean是单例的,如果你希望你写的一个bean不是单例,除了配置文件设置外,现在流行的都是实现这个接口的isSingleton方法,返回false即可。此接口,因能力有限,无法感觉其最大作用,读者自YY。package org.springframework.beans.factory; import org.springframework.lang.Nullable; public interface FactoryBean<T> { @Nullable T getObject() throws Exception; @Nullable Class<?> getObjectType(); default boolean isSingleton() { return true; } }
- SmartLifecycle接口
一般什么时候需要用到实现这个接口呢?这位博主说的更好:如果业务上需要在spring容器启动和关闭的时候做一些操作,比如启动netty的服务端、优雅的关闭服务端。从上述列举中可以看出,感知容器变化的能力最终来自Lifecycle,而SmartLifecycle只是Lifecycle的增强版,可以自定义优先级(getPhase),自主决定是否随容器启动(isAutoStartup),以及停止时能接受一个runnable对象(stop(Runnable))https://blog.csdn.net/boling_cavalry/article/details/82051356public interface SmartLifecycle extends Lifecycle, Phased { int DEFAULT_PHASE = Integer.MAX_VALUE; default boolean isAutoStartup() { return true; } default void stop(Runnable callback) { stop(); callback.run(); } @Override default int getPhase() { return DEFAULT_PHASE; } } public interface Lifecycle { void start(); void stop(); boolean isRunning(); } public interface Phased { //Return the phase value of this object. int getPhase(); }
- ApplicationListener、ApplicationEventPublisher接口
可以监听某个事件event,监听的event类型就是接口中的E,当有人publish事件类型E的时候,实现了ApplicationListener并且监听类型为E的类就会触发onApplicationEvent方法。Spring内部有大量的内置事件,看源码能感受到。
此接口应用也极其广泛,当你想在某些操作发生的时候,触发某些操作,可以用此接口。比如我们程序员,当你知道你家里发财了,有10个亿的时候,你肯定第一想知道,并且立马辞职不干了~package org.springframework.context; import java.util.EventListener; public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { void onApplicationEvent(E event); } public interface ApplicationEventPublisher { void publishEvent(ApplicationEvent event); void publishEvent(Object event); }
//定义一个事件类型 import org.springframework.context.ApplicationEvent; public class MoneyGetEvent extends ApplicationEvent { public MoneyGetEvent(Object source) { super(source); } } //发布事件 import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; public class PublishEventClass implements ApplicationEventPublisherAware { private ApplicationEventPublisher eventPublisher; /** * 实现了ApplicationEventPublisherAware接口,容器加载该bean的时候会调用此setApplicationEventPublisher方法, * 给该bean的eventPublisher属性赋值,此对象用来发布事件,发布后,会触发对此事件类型感兴趣的bean的 */ @Override public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) { this.eventPublisher = eventPublisher; } //当调用该方法的时候,会触发MoneyGetEventListener的onApplicationEvent方法 public void moneyGet() { eventPublisher.publishEvent(new MoneyGetEvent("儿子,家里拆迁分了10个亿,还是美元")); } } //监听事件 import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; @Component public class MoneyGetEventListener implements ApplicationListener<MoneyGetEvent> { @Override public void onApplicationEvent(MoneyGetEvent event) { System.out.println("老板,我摊牌了,我是亿万富翁,上你个屁班!"); } }
- 自定义Spring Boot Start
spring-boot-starter:spring-boot可以省略众多的繁琐配置,它的众多starter可以说是功不可没。例如spring-boot中集成redis,只需要pom.xml中引入spring-boot-starter-data-redis,配置文件中加入spring.redis.database等几个关键配置项即可,常用的starter还有spring-boot-starter-web、spring-boot-starter-test、spring-boot-starter-jdbc,相比于传统的xml配置可以说是大大减少了集成的工作量。SpringBoot启动时会找到starter jar包中的resources/META-INF/spring.factories文件,根据spring.factories文件中的配置,找到需要自动配置的类,读取例如:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.test.springboot.starter.helloworld.configuration.MyAutoConfiguration
指定的Configuration,根据Configuration上的Conditional条件自动创建bean,注入容器(spring.factories并非是必须的,也可以在启动类上添加如下注解进行自动配置:@ImportAutoConfiguration({MyAutoConfiguration.class}))
精彩示例:https://blog.csdn.net/boling_cavalry/article/details/82956512
常见注解:@ConditionalOnBean:当容器中有指定的Bean的条件下 @ConditionalOnClass:当类路径下有指定的类的条件下 @ConditionalOnExpression:基于SpEL表达式作为判断条件 @ConditionalOnJava:基于JVM版本作为判断条件 @ConditionalOnJndi:在JNDI存在的条件下查找指定的位置 @ConditionalOnMissingBean:当容器中没有指定Bean的情况下 @ConditionalOnMissingClass:当类路径下没有指定的类的条件下 @ConditionalOnNotWebApplication:当前项目不是Web项目的条件下 @ConditionalOnProperty:指定的属性是否有指定的值 @ConditionalOnResource:类路径下是否有指定的资源 @ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者在有多个Bean的情况下,用来指定首选的Bean @ConditionalOnWebApplication:当前项目是Web项目的条件下
- Spring的事务管理器
- ApplicationContextInitializer
TODO......