springboot的服务定位模式

发布时间:2024年01月24日

一、文件解析器的例子

在开发中我们可能会解析CSV,JSON等文件类型,显然要用策略模式

?我们先定义一个Parser接口

public interface Parser {
  
  void parse(String input);
}

Parser接口的实现类有JSONParser,CSVParser

@Component("CSV")
public class CSVParser implements Parser{

  @Override
  public void parse(String input) {
    System.out.println("csv");
  }
}
@Component("JSON")
public class JSONParser implements Parser{

  @Override
  public void parse(String input) {
    System.out.println("json");
  }
}

然后我们定义一个工厂来获取Parser对象

public interface ParserFactory {
  
  Parser getParser(ContentType type);

}

在该工厂方法的参数是一个枚举

public enum ContentType {
  JSON,
  XML,
  TEXT,
  HTML,
  IMAGE,
  OTHER;
}

?写一个配置类

@Configuration
public class ParserConfig {
  
  @Bean
  public FactoryBean serviceLocatorFactoryBean(){
    ServiceLocatorFactoryBean factoryBean = new ServiceLocatorFactoryBean();
    factoryBean.setServiceLocatorInterface(ParserFactory.class);
    return factoryBean;
  }

}

测试

 @Autowired
  private ParserFactory parserFactory;

  @Test
  void contextLoads() {
    Parser parser = parserFactory.getParser(ContentType.JSON);
    parser.parse("{'name':'John'}");
  }

?二、原理

????????ServiceLocatorFactoryBean实现了接口FactoryBean和InitializingBean,实现InitializingBean会在初始化ServiceLocatorFactoryBean调用afterPropertiesSet方法,具体实现如下代码

	@Override
	public void afterPropertiesSet() {
		if (this.serviceLocatorInterface == null) {
			throw new IllegalArgumentException("Property 'serviceLocatorInterface' is required");
		}

		// Create service locator proxy.
		this.proxy = Proxy.newProxyInstance(
				this.serviceLocatorInterface.getClassLoader(),
				new Class<?>[] {this.serviceLocatorInterface},
				new ServiceLocatorInvocationHandler());
	}

????????在afterPropertiesSet主要给ServiceLocatorFactoryBean的成员变量proxy赋值,生成代理对象,其中接口就是我们前面的ParserFactory。

? ? ? ? 我们知道实现FactoryBean可以帮助我们创建bean,其中getObject可以获得bean,实现内容如下?

@Override
	@Nullable
	public Object getObject() {
		return this.proxy;
	}

?getObject返回的ParserFactory的代理对象,生成动态代理方式是采用JDK代理,主要关注invoke方法,ServiceLocatorFactoryBean的内部类,实现类接口InvocationHandler

	@Override
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			....
			return invokeServiceLocatorMethod(method, args);	
		}


	private Object invokeServiceLocatorMethod(Method method, Object[] args) throws Exception {
			Class<?> serviceLocatorMethodReturnType = getServiceLocatorMethodReturnType(method);
			try {
				String beanName = tryGetBeanName(args);
				Assert.state(beanFactory != null, "No BeanFactory available");
				if (StringUtils.hasLength(beanName)) {
					// Service locator for a specific bean name
					return beanFactory.getBean(beanName, serviceLocatorMethodReturnType);
				}
				else {
					// Service locator for a bean type
					return beanFactory.getBean(serviceLocatorMethodReturnType);
				}
			}
			catch (BeansException ex) {
				if (serviceLocatorExceptionConstructor != null) {
					throw createServiceLocatorException(serviceLocatorExceptionConstructor, ex);
				}
				throw ex;
			}
		}


    

?invoke主要先根据方法参数获得beanName,通过beanFactory获得bean实例,因此,要特别注意,传入工厂方法的参数要与被spring管理的bean的名字一致才行

文章来源:https://blog.csdn.net/qq_41891244/article/details/135830120
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。