在介紹策略工廠的實現(xiàn)前,我們要先了解spring中beanFactory:
BeanFactory
作為IOC服務(wù)的提供者,通過XmlBeanFactory來得到實例
生產(chǎn)Bean的工廠,采用延遲初始化策略(只有在需要某個對象時,才進行初始化和依賴注入);通常會用xml文件來注冊并管理各個業(yè)務(wù)對象之間的依賴關(guān)系
DefaultListableBeanFactory實現(xiàn)了BeanFactory接口和BeanDefinitionRegistry接口(負責(zé)Bean的注冊管理)
屬性鍵值對注入PropertyValue
這里的key:group,value:name
位于beans包下,是bean屬性鍵值對的封裝,緩存了對key-value解析相關(guān)的信息,避免重復(fù)解析
-
AttributeAccessor
可以訪問對象的屬性或?qū)傩愿郊拥綄ο笊稀?/li>
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
實現(xiàn)了 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;
//屬性值是否進行了屬性轉(zhuǎn)換
private boolean converted = false;
//類型轉(zhuǎn)換后的屬性值
@Nullable
private Object convertedValue;
//屬性值是否需要進行轉(zhuǎn)換
@Nullable
volatile Boolean conversionNecessary;
//緩存解析后的屬性名稱
@Nullable
transient volatile Object resolvedTokens;
MutablePropertyValues
PropertyValues的默認實現(xiàn)類是MutablePropertyValues
MutablePropertyValues:
-
內(nèi)部維護了一個
List<PropertyValue> propertyValueList
,將屬性值轉(zhuǎn)換為PropertyValue進行存儲
Bean的結(jié)構(gòu)圖:
每一個受管的對象,在容器中都會有一個BeanDefinition的實例與之對應(yīng),BeanDefinition存儲對象的信息,包括: -
對應(yīng)的對象的class類型,是否抽象類,構(gòu)造方法參數(shù)及其他信息
-
beanName就是實例名
實現(xiàn)策略工廠:
注解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;
}
創(chuàng)建策略工廠實現(xiàn)類
管理所有的方法文章來源:http://www.zghlxwxcb.cn/news/detail-500803.html
/**
* 策略工廠
* 當你使用注解 StrategyAnnotation 在類上面
* 那么會通過 RegisterMapDefinition 去自動創(chuàng)建策略工廠。
*
* 策略工廠的名稱就是 StrategyAnnotation 定義的group.
*
* 支持的state 參數(shù),就是 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("獲取對象失敗,狀態(tài):" + state);
}
return t;
}
public void setLocalMap(Map<String, T> localMap) {
this.localMap = localMap;
}
public Map<String, T> getLocalMap() {
return Collections.unmodifiableMap(this.localMap);
}
}
RegisterMapDefinition
自動創(chuàng)建策略工廠文章來源地址http://www.zghlxwxcb.cn/news/detail-500803.html
- 獲取注解的group
- 首次registry這個groupBean
- 獲取這個groupBean的BeanDefinition
- 遍歷注解的name
- 通過定義的key(localMap)獲得PropertyValue屬性值
- 首次屬性值為空,創(chuàng)建一個PropertyValue(以localMap為key,ManagedMap為value)
- 將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("批量創(chuàng)建策略實例").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);
}
}
}
}
到了這里,關(guān)于設(shè)計模式-策略工廠的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!