Давайте начнем с циклической зависимости.
trait A {
selfA: B =>
def fa: Int }
trait B {
selfB: A =>
def fb: String }
Тем не менее, модульность этого решения не так велика, как может показаться на первый взгляд, потому что вы можете переопределить собственные типы следующим образом:
trait A1 extends A {
selfA1: B =>
override def fb = "B's String" }
trait B1 extends B {
selfB1: A =>
override def fa = "A's String" }
val myObj = new A1 with B1
Хотя, если вы переопределите член При самостоятельном вводе вы теряете доступ к исходному члену, доступ к которому по-прежнему возможен через супер, используя наследование. Итак, что действительно выигрывает от использования наследования:
trait AB {
def fa: String
def fb: String }
trait A1 extends AB
{ override def fa = "A's String" }
trait B1 extends AB
{ override def fb = "B's String" }
val myObj = new A1 with B1
Теперь я не могу утверждать, что понимаю все тонкости шаблона торта, но мне кажется, что основной метод обеспечения модульности - это скорее композиция чем наследование или самопознание.
Версия наследования короче, но главная причина, по которой я предпочитаю наследование по сравнению с типами self, заключается в том, что мне гораздо сложнее получить правильный порядок инициализации с типами self. Однако есть некоторые вещи, которые вы можете делать с типами себя, которые вы не можете делать с наследованием. Сами типы могут использовать тип, в то время как наследование требует черты или класса, как в:
trait Outer
{ type T1 }
trait S1
{ selfS1: Outer#T1 => } //Not possible with inheritance.
Вы даже можете сделать:
trait TypeBuster
{ this: Int with String => }
Хотя вы никогда не сможете создать его экземпляр , Я не вижу какой-либо абсолютной причины неспособности наследовать от типа, но я, конечно, чувствую, что было бы полезно иметь классы и свойства конструктора путей, поскольку у нас есть свойства / классы конструктора типов. Как, к сожалению,
trait InnerA extends Outer#Inner //Doesn't compile
У нас есть это:
trait Outer
{ trait Inner }
trait OuterA extends Outer
{ trait InnerA extends Inner }
trait OuterB extends Outer
{ trait InnerB extends Inner }
trait OuterFinal extends OuterA with OuterB
{ val myV = new InnerA with InnerB }
Или это:
trait Outer
{ trait Inner }
trait InnerA
{this: Outer#Inner =>}
trait InnerB
{this: Outer#Inner =>}
trait OuterFinal extends Outer
{ val myVal = new InnerA with InnerB with Inner }
Еще один момент, на который следует обратить особое внимание, заключается в том, что черты могут расширять классы. Спасибо Дэвиду Маклверу за указание на это. Вот пример из моего собственного кода:
class ScnBase extends Frame
abstract class ScnVista[GT <: GeomBase[_ <: TypesD]](geomRI: GT) extends ScnBase with DescripHolder[GT] )
{ val geomR = geomRI }
trait EditScn[GT <: GeomBase[_ <: ScenTypes]] extends ScnVista[GT]
trait ScnVistaCyl[GT <: GeomBase[_ <: ScenTypes]] extends ScnVista[GT]
ScnBase
наследуется от класса фрейма Swing , так что он может быть использован как собственный тип, а затем смешан в конце ( при создании экземпляра). Однако, val geomR
необходимо инициализировать, прежде чем он будет использован для наследования черт. Таким образом, нам нужен класс для обеспечения предварительной инициализации geomR
. Класс ScnVista
может затем наследоваться множеством ортогональных признаков, которые сами могут наследоваться. Использование параметров нескольких типов (обобщений) предлагает альтернативную форму модульности.
Обновление :
На основе обновления вопроса я предлагаю:
] Bean-компонент ServiceResolver
, который обрабатывает все, что вам нужно, на основе ввода клиента; Затем ServiceResolver
может либо в init-методе
, либо при каждом вызове определять значения, возвращаемые клиенту , основанный, например, на поиске JNDI или переменных окружения.
Но перед этим вы можете взглянуть на доступные параметры конфигурации . Вы можете либо:
Если вам нужно для поиска свойств из настраиваемого местоположения, посмотрите org.springframework.beans.factory.config.BeanFactoryPostProcessor
и как реализован org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
.
Создайте экземпляр RmiProxyFactoryBean
и настройте свойство serviceUrl
прямо в коде:
String serverHost = "www.example.com";
RmiProxyFactoryBean factory = new RmiProxyFactoryBean();
factory.setServiceUrl("rmi://" + serverHost + ":80/MyService");
factory.setServiceInterface(MyService.class);
try {
factory.afterPropertiesSet();
} catch (Exception e) {
throw new RuntimeException(
"Problem initializing myService factory", e);
}
MyService myService = (MyService) factory.getObject();
Мое существующее решение включает определение нового MapAwareApplicationContext, который принимает Map в качестве дополнительного аргумента конструктора.
public MapAwareApplicationContext(final URL[] configURLs,
final String[] newConfigLocations,
final Map<String, String> additionalProperties) {
super(null);
//standard constructor content here
this.map = new HashMap<String, String>(additionalProperties);
refresh();
}
Он переопределяет postProcessBeanFactory () для добавления в MapAwareProcessor:
protected void postProcessBeanFactory(
final ConfigurableListableBeanFactory beanFactory) {
beanFactory.addBeanPostProcessor(new MapAwareProcessor(this.map));
beanFactory.ignoreDependencyInterface(MapAware.class);
}
MapAwareProcessor реализует postProcessBeforeInitialization () чтобы вставить карту в любой тип, реализующий интерфейс MapAware:
public Object postProcessBeforeInitialization(final Object bean,
final String beanName) {
if (this.map != null && bean instanceof MapAware) {
((MapAware) bean).setMap(this.map);
}
return bean;
}
Затем я добавляю новый компонент в свою конфигурацию, чтобы объявить MapAwarePropertyPlaceholderConfigurer:
<bean id="propertyConfigurer"
class="com.hsbc.r2ds.spring.MapAwarePropertyPlaceholderConfigurer"/>
Конфигуратор реализует MapAware, поэтому он будет внедрен вместе с картой, как указано выше. Затем он реализует resolvePlaceholder () для разрешения свойств из карты или делегирует родительскому конфигуратору:
protected String resolvePlaceholder(final String placeholder,
final Properties props, final int systemPropertiesMode) {
String propVal = null;
if (this.map != null) {
propVal = this.map.get(placeholder);
}
if (propVal == null) {
propVal = super.resolvePlaceholder(placeholder, props);
}
return propVal;
}
PropertyPlaceholderConfigurer может получать свойства из файла, это правда, но если он не может их найти, он возвращается к использованию системных свойств. Это звучит как жизнеспособный вариант для вашего клиентского приложения, просто передайте системное свойство с помощью -D при запуске клиента.
Из javadoc
Конфигуратор также проверит против системные свойства (например, "user.dir"), если он не может разрешить заполнитель с любое из указанных свойств. это можно настроить через "systemPropertiesMode".
See http://forum.springsource.org/showthread.php?t=71815
TestClass.java
package com.spring.ioc; публичный класс TestClass { Сначала частная Стринг; частная Строка вторая; public String getFirst() { Возвращайся первым; } public void setFirst(Сначала строка) { это. Первый = первый; } публичная Строка getSecond() { возвращайся через секунду; } public void setSecond(String second) { это. Секунда = секунда; } }
SpringStart.java
package com.spring; импорт java.util.Properties; импорт com.spring.ioc.TestClass; импорт org.springframework.context.support.ClassPathXmlApplicationContext; импорт org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; публичный класс SpringStart { public static void main(String[] args) выбрасывает исключение {{ PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer(); Свойства properties = new Properties(); properties.setProperty("first.prop", "first value"); properties.setProperty("second.prop", "второе значение"); configurer.setProperties(properties); ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(); context.addBeanFactoryPostProcessor(configurer); context.setConfigLocation("spring-config.xml"); context.refresh(); TestClass testClass = (TestClass)context.getBean("testBean"); System.out.println(testClass.getFirst()); System.out.println(testClass.getSecond()); } }
spring-config.xml
<бобы xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:схемаЛокация=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<имя собственности="first" value="${first.prop}"/> <имя свойства="второе" значение="${секунда.prop}"/> бобыВыход:
первое значение. второе значение