本节主要的知识点InitializingBean接口和DependsOn注解
书接上回,我们要用设计模式改造这个if/else
public static void main(String[] args){
String type = "common";
operateByType(type);
}
private static void operateByType(String type) {
if ("common".equals(type)){
System.out.println("先查询缓存,缓存没有在查询数据库,同时更新缓存");
}
if ("update".equals(type)){
System.out.println("直接更新缓存");
}
}
上回我们使用ApplicationContextAware接口,实现了一个工厂+策略模式。这回我们换一种方式使用spring bean的 InitializingBean 接口重写afterPropertiesSet方法来实现工厂 +策略模式。
InitializingBean 是 Spring 框架中的一个接口,用于在 Spring Bean 初始化时执行自定义的初始化逻辑。当一个 Spring Bean 实现了 InitializingBean 接口,它必须实现接口中的 afterPropertiesSet 方法。这个方法会在 Bean 的属性设置完成后(也就是依赖注入完成后),在 Bean 被容器初始化之后被调用。
定义一个接口
public interface AttributeNumberService {
void operateByType();
}
定义一个工厂类
public class AttributeNumberFactory {
private static final Map<String, AttributeNumberService> processServiceMap = new ConcurrentHashMap<>();
public static AttributeNumberService get(String type) {
Assert.notNull(type, "type can't be null");
return processServiceMap.get(type);
}
public static void put(String type,AttributeNumberService attributeNumberService){
Assert.notNull(type, "transCode can't be null");
processServiceMap.put(type, attributeNumberService);
}
}
定义一个SpringBeanUtil,从spring上下文获取bean
@Component
public class SpringBeanUtil implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringBeanUtil.context = applicationContext;
}
/** 从静态变量applicationContext中得到Bean, 自动转型为所赋值对象的类型. */
public static <T> T getBean(Class<T> clazz) {
return context.getBean(clazz);
}
}
ApplicationContextAware 接口是 Spring 框架中的一个接口,用于实现对 Spring 应用上下文(ApplicationContext)的感知,从而使一个类能够获取对应用上下文的引用。通过实现这个接口,类可以访问 Spring 容器中的 bean 实例和其他 Spring 特性。
这个接口定义了一个方法 setApplicationContext,需要在实现类中实现。当 Spring 容器初始化 bean 时,如果 bean 实现了 ApplicationContextAware 接口,容器会自动调用 setApplicationContext 方法,并将应用上下文的引用作为参数传递给这个方法。
AttributeNumberService实现类CommonAttributeNumberServiceImpl
@Service
@DependsOn(value = {"springBeanUtil"})
public class CommonAttributeNumberServiceImpl implements AttributeNumberService,InitializingBean{
@Override
public void operateByType() {
System.out.println("先查询缓存,缓存没有在查询数据库,同时更新缓存");
}
@Override
public void afterPropertiesSet() throws Exception {
AttributeNumberFactory.put("common", SpringBeanUtil.getBean(CommonAttributeNumberServiceImpl.class));
}
}
这里我们实现了InitializingBean的afterPropertiesSet方法目的是把CommonAttributeNumberServiceImpl实例放入工厂中,我们使用SpringBeanUtil获取CommonAttributeNumberServiceImpl的实例放入工厂。
使用DependsOn注解是因为springBeanUtil要先加载我们才能使用springBeanUtil工具类
@DependsOn 注解是 Spring 框架中的一个注解,用于指定 bean 之间的初始化顺序。通过使用 @DependsOn 注解,您可以明确指定一个 bean 依赖于其他 bean,以确保在容器初始化时,依赖的 bean 先于当前 bean 初始化
@Service
@DependsOn(value = {"springBeanUtil"})
public class UpdateAttributeNumberServiceImpl implements AttributeNumberService, InitializingBean {
@Override
public void operateByType() {
System.out.println("直接更新缓存");
}
@Override
public void afterPropertiesSet() throws Exception {
AttributeNumberFactory.put(
"update", SpringBeanUtil.getBean(UpdateAttributeNumberServiceImpl.class));
}
}
然后就可以使用啦
@SpringBootTest()
class ShejimoshiGcApplicationTests {
@Test
void operateByTypeTest() {
AttributeNumberService common = AttributeNumberFactory.get("common");
common.operateByType();
}
}
我们发现这个方法比上次的方法更复杂些,所以在工作中我们还是用上次的方法比较好