设计模式-策略工厂

在介绍策略工厂的实现前,我们要先了解spring中beanFactory:

BeanFactory

作为IOC服务的提供者,通过XmlBeanFactory来得到实例

生产Bean的工厂,采用延迟初始化策略(只有在需要某个对象时,才进行初始化和依赖注入);通常会用xml文件来注册并管理各个业务对象之间的依赖关系

DefaultListableBeanFactory实现了BeanFactory接口和BeanDefinitionRegistry接口(负责Bean的注册管理)
在这里插入图片描述

属性键值对注入PropertyValue

这里的key:group,value:name

位于beans包下,是bean属性键值对的封装,缓存了对key-value解析相关的信息,避免重复解析

在这里插入图片描述

  • AttributeAccessor 可以访问对象的属性或将属性附加到对象上。
public interface AttributeAccessor {
	//增删改查
	void setAttribute(String name, @Nullable Object value);
	@Nullable
	Object getAttribute(String name);
	@SuppressWarnings("unchecked")
	default <T> T computeAttribute(String name, Function<String, T> computeFunction) {
		Assert.notNull(name, "Name must not be null");
		Assert.notNull(computeFunction, "Compute function must not be null");
		Object value = getAttribute(name);
		if (value == null) {
			value = computeFunction.apply(name);
			Assert.state(value != null,
					() -> String.format("Compute function must not return null for attribute named '%s'", name));
			setAttribute(name, value);
		}
		return (T) value;
	}
	@Nullable
	Object removeAttribute(String name);
	boolean hasAttribute(String name);
	String[] attributeNames();
}
  • BeanMetadataElement 持有属性信息的对象。
public interface BeanMetadataElement {

	@Nullable
	default Object getSource() {
		return null;
	}

}
  • BeanMetadataAttributeAccessor 实现了 AttributeAccessor和 BeanMetadataElement 两个接口,属性为 BeanMetadataAttribute 对象
public class BeanMetadataAttributeAccessor extends AttributeAccessorSupport implements BeanMetadataElement {

	@Nullable
	private Object source;

	public void setSource(@Nullable Object source) {
		this.source = source;
	}

	@Override
	@Nullable
	public Object getSource() {
		return this.source;
	}
}
  • PropertyValue 属性键值对
public class PropertyValue extends BeanMetadataAttributeAccessor implements Serializable {
	//属性名称
	private final String name;
	//属性值
	@Nullable
	private final Object value;
	//属性值是否是optional
	private boolean optional = false;
	//属性值是否进行了属性转换
	private boolean converted = false;
	//类型转换后的属性值
	@Nullable
	private Object convertedValue;
	//属性值是否需要进行转换
	@Nullable
	volatile Boolean conversionNecessary;
	//缓存解析后的属性名称
	@Nullable
	transient volatile Object resolvedTokens;

MutablePropertyValues

在这里插入图片描述

PropertyValues的默认实现类是MutablePropertyValues

MutablePropertyValues:

  • 内部维护了一个List<PropertyValue> propertyValueList将属性值转换为PropertyValue进行存储
    Bean的结构图:
    在这里插入图片描述
    每一个受管的对象,在容器中都会有一个BeanDefinition的实例与之对应,BeanDefinition存储对象的信息,包括:

  • 对应的对象的class类型,是否抽象类,构造方法参数及其他信息

  • beanName就是实例名

实现策略工厂:

注解StrategyAnnotation

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface StrategyAnnotation {
    /**
     * 策略类型名称,可以支持多个
     *
     * @return
     */
    String[] name() default "";

    /**
     * 默认组为: defaultGroup
     *
     * @return
     */
    String group() default "defaultGroup";

    /**
     * 是否默认类型
     *
     * @return
     */
    boolean isDefault() default false;
}

创建策略工厂实现类

管理所有的方法

/**
 * 策略工厂
 * 当你使用注解 StrategyAnnotation 在类上面
 * 那么会通过 RegisterMapDefinition 去自动创建策略工厂。
 *
 * 策略工厂的名称就是 StrategyAnnotation 定义的group.
 *
 * 支持的state 参数,就是 StrategyAnnotation 定义的 name
 *
 */
public class StrategyFactory<T> {
    //key是策略类型,value是具体策略
    Map<String, T> localMap;

    public T getObjectByState(String state) {
        return localMap.get(state);
    }

    public T defaultObject(String state) {
        T t = localMap.get(state);
        if (t == null) {
            t = localMap.get(null);
        }
        return t;
    }

    public T getObjectThrowException(String state) {
        T t = localMap.get(state);
        if (t == null) {
            throw new IllegalStateException("获取对象失败,状态:" + state);
        }
        return t;
    }

    public void setLocalMap(Map<String, T> localMap) {
        this.localMap = localMap;
    }

    public Map<String, T> getLocalMap() {
        return Collections.unmodifiableMap(this.localMap);
    }
}

RegisterMapDefinition

自动创建策略工厂

  1. 获取注解的group
  2. 首次registry这个groupBean
  3. 获取这个groupBean的BeanDefinition
  4. 遍历注解的name
  5. 通过定义的key(localMap)获得PropertyValue属性值
  6. 首次属性值为空,创建一个PropertyValue(以localMap为key,ManagedMap为value)
  7. 将localMap这个PropertyValue属性添加到propertyValues中即可
/**
 * 策略配置加载器
 */
@Component
public class RegisterMapDefinition implements BeanDefinitionRegistryPostProcessor {

    public static final String LOCAL_MAP_PROPERTY = "localMap";
    Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 本文加载有注解的bean为map 作为策略映射,
     *
     * @param beanFactory
     * @throws BeansException
     * @see StrategyAnnotation
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    }

    private void registerGroupMap(BeanDefinitionRegistry registry, StrategyAnnotation strategyAnnotation, String beanName, BeanDefinition beanDefinition) {
        String groupBean = strategyAnnotation.group();
        if (!registry.containsBeanDefinition(groupBean)) {
            RootBeanDefinition strategyFactoryDefinition = new RootBeanDefinition();
            strategyFactoryDefinition.setBeanClass(StrategyFactory.class);
            registry.registerBeanDefinition(groupBean, strategyFactoryDefinition);
        }
        BeanDefinition groupBeanDefinition = registry.getBeanDefinition(groupBean);

        String[] names = strategyAnnotation.name();
        for (String name : names) {
            MutablePropertyValues propertyValues = groupBeanDefinition.getPropertyValues();
            PropertyValue localMap = propertyValues.getPropertyValue(LOCAL_MAP_PROPERTY);
            if (localMap == null) {
                localMap = new PropertyValue(LOCAL_MAP_PROPERTY, new ManagedMap<>());
                propertyValues.addPropertyValue(localMap);
            }
            ManagedMap<TypedStringValue, BeanReference> stringObjectManagedMap =
                    (ManagedMap<TypedStringValue, BeanReference>) localMap.getValue();
            stringObjectManagedMap.put(new TypedStringValue(name), new RuntimeBeanReference(beanName));
            if (strategyAnnotation.isDefault()) {
                stringObjectManagedMap.put(null, new RuntimeBeanReference(beanName));
            }
            propertyValues.addPropertyValue(localMap);
        }
    }


    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        String op = "RegisterMapDefinition.postProcessBeanDefinitionRegistry";
        logger.info(Logs.op(op).msg("批量创建策略实例").toString());
        //获取所有的beanName
        String[] strategyAnnotationsArray = registry.getBeanDefinitionNames();
        //遍历每个beanName
        for (String beanName : strategyAnnotationsArray) {
            BeanDefinition beanDefinition = registry.getBeanDefinition(beanName);
            try {
                //获得bean的类名
                String beanClassName = beanDefinition.getBeanClassName();
                if (beanClassName == null) {
                    continue;
                }
				//找到类对象
                Class<?> clazz = Class.forName(beanClassName);
                //获取类对象上的StrategyAnnotations注解
                StrategyAnnotations annotation = AnnotationUtils.findAnnotation(clazz, StrategyAnnotations.class);
                //有StrategyAnnotations注解的进行注册
                if (annotation != null) {
                    for (StrategyAnnotation strategyAnnotation : annotation.value()) {
                        registerGroupMap(registry, strategyAnnotation, beanName, beanDefinition);
                    }
                }

                StrategyAnnotation strategyAnnotation = AnnotationUtils.findAnnotation(clazz, StrategyAnnotation.class);
                if(strategyAnnotation!=null){
                    registerGroupMap(registry, strategyAnnotation, beanName, beanDefinition);
                }

            } catch (ClassNotFoundException e) {
                logger.debug(Logs.op(op).msg("策略加载器加载指定类不存在").toString(), e);
            }

        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值