本文将带您了解关于openfire用户认证多数据源配置1HybridUserPropertyProvider的新内容,同时我们还将为您解释opencloud多认证中心的相关知识,另外,我们还将为您提供
本文将带您了解关于openfire 用户认证多数据源配置 1 HybridUserPropertyProvider的新内容,同时我们还将为您解释opencloud 多认证中心的相关知识,另外,我们还将为您提供关于.properties文件中的PropertyPlaceholderConfigurer和环境变量、Big impact when set property type in-properly、com.hazelcast.config.properties.PropertyTypeConverter的实例源码、com.intellij.uiDesigner.propertyInspector.properties.BindingProperty的实例源码的实用信息。
本文目录一览:- openfire 用户认证多数据源配置 1 HybridUserPropertyProvider(opencloud 多认证中心)
- .properties文件中的PropertyPlaceholderConfigurer和环境变量
- Big impact when set property type in-properly
- com.hazelcast.config.properties.PropertyTypeConverter的实例源码
- com.intellij.uiDesigner.propertyInspector.properties.BindingProperty的实例源码
openfire 用户认证多数据源配置 1 HybridUserPropertyProvider(opencloud 多认证中心)
openfire 用户认证多数据源配置 1
/*
* Copyright 2017 IgniteRealtime.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.openfire.user.property;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.util.JiveGlobals;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Delegate UserPropertyProvider operations among up to three configurable provider implementation classes.
*
* This implementation will not explicitly verify if a user exists, when operating on its properties. The methods of
* this implementation will <em>not</em> throw {@link org.jivesoftware.openfire.user.UserNotFoundException}.
*
* This class related to, but is distinct from {@link MappedUserPropertyProvider}. The Hybrid variant of the provider
* iterates over providers, operating on the first applicable instance. The Mapped variant, however, maps each user to
* exactly one provider.
*
* To use this provider, use the following system property definition:
*
* <ul>
* <li>{@code provider.userproperty.className = org.jivesoftware.openfire.user.HybridUserPropertyProvider}</li>
* </ul>
*
* Next, configure up to three providers, by setting these properties:
* <ol>
* <li>{@code hybridUserPropertyProvider.primaryProvider.className = fully.qualified.ClassUserPropertyProvider}</li>
* <li>{@code hybridUserPropertyProvider.secondaryProvider.className = fully.qualified.ClassUserPropertyProvider}</li>
* <li>{@code hybridUserPropertyProvider.tertiaryProvider.className = fully.qualified.ClassUserPropertyProvider}</li>
* </ol>
*
* @author Guus der Kinderen, guus.der.kinderen@gmail.com
*/
public class HybridUserPropertyProvider implements UserPropertyProvider
{
private static final Logger Log = LoggerFactory.getLogger( HybridUserPropertyProvider.class );
private final List<UserPropertyProvider> providers = new ArrayList<>();
public HybridUserPropertyProvider()
{
// Migrate user provider properties
JiveGlobals.migrateProperty( "hybridUserPropertyProvider.primaryProvider.className" );
JiveGlobals.migrateProperty( "hybridUserPropertyProvider.secondaryProvider.className" );
JiveGlobals.migrateProperty( "hybridUserPropertyProvider.tertiaryProvider.className" );
// Load primary, secondary, and tertiary user providers.
final UserPropertyProvider primary = MappedUserPropertyProvider.instantiate( "hybridUserPropertyProvider.primaryProvider.className" );
if ( primary != null )
{
providers.add( primary );
}
final UserPropertyProvider secondary = MappedUserPropertyProvider.instantiate( "hybridUserPropertyProvider.secondaryProvider.className" );
if ( secondary != null )
{
providers.add( secondary );
}
final UserPropertyProvider tertiary = MappedUserPropertyProvider.instantiate( "hybridUserPropertyProvider.tertiaryProvider.className" );
if ( tertiary != null )
{
providers.add( tertiary );
}
// Verify that there''s at least one provider available.
if ( providers.isEmpty() )
{
Log.error( "At least one UserPropertyProvider must be specified via openfire.xml or the system properties!" );
}
}
/**
* Returns the properties from the first provider that returns a non-empty collection.
*
* When none of the providers provide properties an empty collection is returned.
*
* @param username The identifier of the user (cannot be null or empty).
* @return A collection, possibly empty, never null.
*/
@Override
public Map<String, String> loadProperties( String username )
{
for ( final UserPropertyProvider provider : providers )
{
try
{
final Map<String, String> properties = provider.loadProperties( username );
if ( !properties.isEmpty() )
{
return properties;
}
}
catch ( UserNotFoundException e )
{
// User not in this provider. Try other providers;
}
}
return Collections.emptyMap();
}
/**
* Returns a property from the first provider that returns a non-null value.
*
* This method will return null when the desired property was not defined in any provider.
*
* @param username The identifier of the user (cannot be null or empty).
* @param propName The property name (cannot be null or empty).
* @return The property value (possibly null).
*/
@Override
public String loadProperty( String username, String propName )
{
for ( final UserPropertyProvider provider : providers )
{
try
{
final String property = provider.loadProperty( username, propName );
if ( property != null )
{
return property;
}
}
catch ( UserNotFoundException e )
{
// User not in this provider. Try other providers;
}
}
return null;
}
/**
* Adds a new property, updating a previous property value if one already exists.
*
* Note that the implementation of this method is equal to that of {@link #updateProperty(String, String, String)}.
*
* First, tries to find a provider that has the property for the provided user. If that provider is read-only, an
* UnsupportedOperationException is thrown. If the provider is not read-only, the existing property value will be
* updated.
*
* When the property is not defined in any provider, it will be added in the first non-read-only provider.
*
* When all providers are read-only, an UnsupportedOperationException is thrown.
*
* @param username The identifier of the user (cannot be null or empty).
* @param propName The property name (cannot be null or empty).
* @param propValue The property value (cannot be null).
*/
@Override
public void insertProperty( String username, String propName, String propValue ) throws UnsupportedOperationException
{
updateProperty( username, propName, propValue );
}
/**
* Updates a property (or adds a new property when the property does not exist).
*
* Note that the implementation of this method is equal to that of {@link #insertProperty(String, String, String)}.
*
* First, tries to find a provider that has the property for the provided user. If that provider is read-only, an
* UnsupportedOperationException is thrown. If the provider is not read-only, the existing property value will be
* updated.
*
* When the property is not defined in any provider, it will be added in the first non-read-only provider.
*
* When all providers are read-only, an UnsupportedOperationException is thrown.
*
* @param username The identifier of the user (cannot be null or empty).
* @param propName The property name (cannot be null or empty).
* @param propValue The property value (cannot be null).
*/
@Override
public void updateProperty( String username, String propName, String propValue ) throws UnsupportedOperationException
{
for ( final UserPropertyProvider provider : providers )
{
try
{
if ( provider.loadProperty( username, propName ) != null )
{
provider.updateProperty( username, propName, propValue );
return;
}
}
catch ( UserNotFoundException e )
{
// User not in this provider. Try other providers;
}
}
for ( final UserPropertyProvider provider : providers )
{
try
{
if ( !provider.isReadOnly() )
{
provider.insertProperty( username, propName, propValue );
return;
}
}
catch ( UserNotFoundException e )
{
// User not in this provider. Try other providers;
}
}
throw new UnsupportedOperationException();
}
/**
* Removes a property from all non-read-only providers.
*
* @param username The identifier of the user (cannot be null or empty).
* @param propName The property name (cannot be null or empty).
*/
@Override
public void deleteProperty( String username, String propName ) throws UnsupportedOperationException
{
// all providers are read-only
if ( isReadOnly() )
{
throw new UnsupportedOperationException();
}
for ( final UserPropertyProvider provider : providers )
{
if ( provider.isReadOnly() )
{
continue;
}
try
{
provider.deleteProperty( username, propName );
}
catch ( UserNotFoundException e )
{
// User not in this provider. Try other providers;
}
}
}
/**
* Returns whether <em>all</em> backing providers are read-only. When read-only, properties can not be created,
* deleted, or modified. If at least one provider is not read-only, this method returns false.
*
* @return true when all backing providers are read-only, otherwise false.
*/
@Override
public boolean isReadOnly()
{
// TODO Make calls concurrent for improved throughput.
for ( final UserPropertyProvider provider : providers )
{
// If at least one provider is not readonly, neither is this proxy.
if ( !provider.isReadOnly() )
{
return false;
}
}
return true;
}
}
.properties文件中的PropertyPlaceholderConfigurer和环境变量
我有一个带有PropertyPlaceholderConfigurer的Spring application-
context.xml,可以从.properties文件中获取属性的值。主和测试源文件夹具有单独的.properties文件。问题是我需要在.properties文件中使用环境变量。但是当我通过以下方式进行操作时:
property.name=${env.SYSTEM_PROPERTY}
我收到以下错误:
org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name ''beanName'' defined in class path resource [com/example/applicationContext.xml]: Could not resolve placeholder ''env.SYSTEM_PROPERTY''
而占位符配置器定义为
<bean> <property name="location" value="classpath:com/example/application.properties"/></bean>
关于如何使property.name解释为环境变量(而不是占位符)的任何想法?
最好的问候,德米特里。
答案1
小编典典我可能会完全更改解决方案:直接注入系统属性,而不是注入引用系统属性的属性
例如
@Value("#{ systemProperties[''JAVA_MY_ENV''] }") private String myVar;
要么
<property name ="myVar" value="#{systemProperties[''JAVA_MY_ENV'']}"/>
我使用这样的属性占位符配置器
<bean id="propertyConfigurer"> <property name="locations"> <list> <value>classpath:someprops.properties</value> </list> </property> <property name="ignoreResourceNotFound" value="true" /> <property name="searchSystemEnvironment" value="true" /> <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
您还必须记住使用以下命令将参数传递给程序
-DJAVA_MY_ENV=xyz
这样,当您运行生产版本时,您可以通过一件事,而在运行测试时,您可以通过另一件事。
同样,我经常做的事情是这样的:
<property name="locations"> <list> <value>classpath:someprops.properties</value> <value>classpath:someprops-{environment}.properties</value> </list> </property>
环境是prod / stage / test / int / ci /
local(每个环境1个-您现在可能只有2个或3个)。您可以将环境变量传递给程序。无论其在本地PC
/测试上的生产/运行情况如何,任何应相同的属性都应位于someprops.properties属性文件中。特定于环境/运行方式的任何内容都将放在更特定的文件中(除非覆盖机制,否则应将其放置在someprops.properties文件以及默认文件中)
例如在classpath:someprops.properties中
url=www.mysite.com
在classpath:someprops-local.properties中
url=localhost
通过使用此基本思想,您可以以干净的方式将测试和程序的正常运行属性分开。
Big impact when set property type in-properly
In sqlserver DB,for the string,we have types: NVARCHR,VARCHAR.
In mapping class,if you use default set the type to "string" but the column type is varchar in DB,that will cause a transfer in DB side when searching comparing,if unfortunately you have a huge data in the table,the DB transer will be more huge,it will deadblock you DB.
To solve it if in DB its type is VARCHAR,in Mapping class should use:
[Property(Type = "AnsiString")] instead.
com.hazelcast.config.properties.PropertyTypeConverter的实例源码
public HerokudiscoveryStrategy(ILogger logger,Map<String,Comparable> properties) { super(logger,properties); String serviceNamesProp = getorNull(new SimplePropertyDeFinition("serviceNames",PropertyTypeConverter.STRING)); if (serviceNamesProp == null) { String formationName = System.getenv("HEROKU_DNS_FORMATION_NAME"); if (formationName == null) { throw new IllegalArgumentException("You must enable Heroku DNS Service discovery for this Hazelcast plugin to work!"); } else { this.serviceNames = Collections.unmodifiableCollection(Arrays.asList(formationName)); } } else { List<String> serviceNamesList = new ArrayList<>(); for (String serviceName : serviceNamesProp.split(";")) { String appName = System.getenv("HEROKU_DNS_APP_NAME"); if (appName == null) { throw new IllegalArgumentException("You must enable Heroku DNS Service discovery for this Hazelcast plugin to work!"); } else { serviceNamesList.add(serviceName + "." + appName); } } this.serviceNames = Collections.unmodifiableCollection(serviceNamesList); } String mergeDelay = getorNull(new SimplePropertyDeFinition("mergeDelay",PropertyTypeConverter.STRING)); System.setProperty("hazelcast.merge.first.run.delay.seconds",mergeDelay == null ? "20" : mergeDelay); // Todo parse /etc/heroku/space-topology.json instead,// but that should go in a separate library Security.setProperty("networkaddress.cache.ttl","20"); Security.setProperty("networkaddress.cache.negative.ttl","0"); }
public ConsuldiscoveryFactory() { List<PropertyDeFinition> properties = new ArrayList<>(); properties.add(new SimplePropertyDeFinition("host",PropertyTypeConverter.STRING)); properties.add(new SimplePropertyDeFinition("port",PropertyTypeConverter.INTEGER)); properties.add(new SimplePropertyDeFinition("name",PropertyTypeConverter.STRING)); this.propertyDeFinitions = Collections.unmodifiableCollection(properties); }
public ConsuldiscoveryFactory() { List<PropertyDeFinition> properties = new ArrayList<>(); properties.add(new SimplePropertyDeFinition("host",PropertyTypeConverter.STRING)); this.propertyDeFinitions = Collections.unmodifiableCollection(properties); }
private static PropertyDeFinition property(String key,PropertyTypeConverter typeConverter) { return property(key,typeConverter,null); }
private static PropertyDeFinition property(String key,PropertyTypeConverter typeConverter,ValueValidator valueValidator) { return new SimplePropertyDeFinition(key,true,valueValidator); }
private static PropertyDeFinition property(String key,null); }
private static PropertyDeFinition property(String key,valueValidator); }
private static PropertyDeFinition property(String key,null); }
private static PropertyDeFinition property(String key,valueValidator); }
com.intellij.uiDesigner.propertyInspector.properties.BindingProperty的实例源码
private static void adjustDuplicates(final Map<RadComponent,RadComponent> duplicates) { for(RadComponent c: duplicates.keySet()) { RadComponent copy = duplicates.get(c); if (c.getBinding() != null) { String binding = BindingProperty.getDefaultBinding(copy); new BindingProperty(c.getProject()).setValueEx(copy,binding); copy.setDefaultBinding(true); } for(IProperty prop: copy.getModifiedProperties()) { if (prop instanceof IntroComponentProperty) { final IntroComponentProperty componentProperty = (IntroComponentProperty)prop; String copyValue = componentProperty.getValue(copy); for(RadComponent original: duplicates.keySet()) { if (original.getId().equals(copyValue)) { componentProperty.setValueEx(copy,duplicates.get(original).getId()); } } } } } }
private static void adjustDuplicates(final Map<RadComponent,duplicates.get(original).getId()); } } } } } }
private static void adjustDuplicates(final Map<RadComponent,duplicates.get(original).getId()); } } } } } }
private static boolean canCreateListener(final ArrayList<RadComponent> selection) { if (selection.size() == 0) return false; final RadRootContainer root = (RadRootContainer)FormEditingUtil.getRoot(selection.get(0)); if (root.getClasstoBind() == null) return false; String componentClass = selection.get(0).getComponentClassName(); for(RadComponent c: selection) { if (!c.getComponentClassName().equals(componentClass) || c.getBinding() == null) return false; if (BindingProperty.findBoundField(root,c.getBinding()) == null) return false; } return true; }
private static void updateBoundFieldType(final GuiEditor editor,final RadComponent oldComponent,final ComponentItem targetItem) { PsiField oldBoundField = BindingProperty.findBoundField(editor.getRootContainer(),oldComponent.getBinding()); if (oldBoundField != null) { final PsiElementFactory factory = JavaPsiFacade.getInstance(editor.getProject()).getElementFactory(); try { PsiType componentType = factory.createTypeFromText(targetItem.getClassName().replace('$','.'),null); new ChangeFieldTypeFix(editor,oldBoundField,componentType).run(); } catch (IncorrectOperationException e) { LOG.error(e); } } }
private void saveButtonGroupIsBound() { if (myGroup.isBound() != myBindToFieldCheckBox.isSelected()) { myGroup.setBound(myBindToFieldCheckBox.isSelected()); notifyListeners(new ChangeEvent(myGroup)); if (myGroup.isBound()) { BindingProperty.updateBoundFieldName(myRootContainer,null,myGroup.getName(),ButtonGroup.class.getName()); } else { BindingProperty.checkRemoveUnusedField(myRootContainer,FormEditingUtil.getNextSaveUndoGroupId(myRootContainer.getProject())); } } }
private void saveButtonGroupName() { String oldName = myGroup.getName(); String newName = myNameTextField.getText(); if (!oldName.equals(newName)) { myGroup.setName(newName); notifyListeners(new ChangeEvent(myGroup)); if (myGroup.isBound()) { BindingProperty.updateBoundFieldName(myRootContainer,oldName,newName,ButtonGroup.class.getName()); } } }
private static boolean canCreateListener(final ArrayList<RadComponent> selection) { if (selection.size() == 0) return false; final RadRootContainer root = (RadRootContainer)FormEditingUtil.getRoot(selection.get(0)); if (root.getClasstoBind() == null) return false; String componentClass = selection.get(0).getComponentClassName(); for(RadComponent c: selection) { if (!c.getComponentClassName().equals(componentClass) || c.getBinding() == null) return false; if (BindingProperty.findBoundField(root,c.getBinding()) == null) return false; } return true; }
private static void updateBoundFieldType(final GuiEditor editor,componentType).run(); } catch (IncorrectOperationException e) { LOG.error(e); } } }
private void saveButtonGroupIsBound() { if (myGroup.isBound() != myBindToFieldCheckBox.isSelected()) { myGroup.setBound(myBindToFieldCheckBox.isSelected()); notifyListeners(new ChangeEvent(myGroup)); if (myGroup.isBound()) { BindingProperty.updateBoundFieldName(myRootContainer,FormEditingUtil.getNextSaveUndoGroupId(myRootContainer.getProject())); } } }
private void saveButtonGroupName() { String oldName = myGroup.getName(); String newName = myNameTextField.getText(); if (!oldName.equals(newName)) { myGroup.setName(newName); notifyListeners(new ChangeEvent(myGroup)); if (myGroup.isBound()) { BindingProperty.updateBoundFieldName(myRootContainer,ButtonGroup.class.getName()); } } }
private static boolean canCreateListener(final ArrayList<RadComponent> selection) { if (selection.size() == 0) return false; final RadRootContainer root = (RadRootContainer)FormEditingUtil.getRoot(selection.get(0)); if (root.getClasstoBind() == null) return false; String componentClass = selection.get(0).getComponentClassName(); for(RadComponent c: selection) { if (!c.getComponentClassName().equals(componentClass) || c.getBinding() == null) return false; if (BindingProperty.findBoundField(root,c.getBinding()) == null) return false; } return true; }
private static void updateBoundFieldType(final GuiEditor editor,componentType).run(); } catch (IncorrectOperationException e) { LOG.error(e); } } }
private void saveButtonGroupIsBound() { if (myGroup.isBound() != myBindToFieldCheckBox.isSelected()) { myGroup.setBound(myBindToFieldCheckBox.isSelected()); notifyListeners(new ChangeEvent(myGroup)); if (myGroup.isBound()) { BindingProperty.updateBoundFieldName(myRootContainer,FormEditingUtil.getNextSaveUndoGroupId(myRootContainer.getProject())); } } }
private void saveButtonGroupName() { String oldName = myGroup.getName(); String newName = myNameTextField.getText(); if (!oldName.equals(newName)) { myGroup.setName(newName); notifyListeners(new ChangeEvent(myGroup)); if (myGroup.isBound()) { BindingProperty.updateBoundFieldName(myRootContainer,ButtonGroup.class.getName()); } } }
private static String[] getFieldNames(final RadComponent component,final String currentName) { final ArrayList<String> result = new ArrayList<String>(); if (currentName != null){ result.add(currentName); } final IRootContainer root = FormEditingUtil.getRoot(component); final String className = root.getClasstoBind(); if (className == null) { return ArrayUtil.toStringArray(result); } final PsiClass aClass = FormEditingUtil.findClasstoBind(component.getModule(),className); if (aClass == null) { return ArrayUtil.toStringArray(result); } final PsiField[] fields = aClass.getFields(); for (final PsiField field : fields) { if (field.hasModifierProperty(PsiModifier.STATIC)) { continue; } final String fieldName = field.getName(); if (Comparing.equal(currentName,fieldName)) { continue; } if (!FormEditingUtil.isBindingUnique(component,fieldName,root)) { continue; } final String componentClassName; if (component instanceof RadErrorComponent) { componentClassName = component.getComponentClassName(); } else if (component instanceof RadHSpacer || component instanceof RadVSpacer) { componentClassName = Spacer.class.getName(); } else { componentClassName = component.getComponentClass().getName(); } final PsiType componentType; try { componentType = JavaPsiFacade.getInstance(component.getProject()).getElementFactory().createTypeFromText(componentClassName,null); } catch (IncorrectOperationException e) { continue; } final PsiType fieldType = field.getType(); if (!fieldType.isAssignableFrom(componentType)) { continue; } result.add(fieldName); } String text = ForminspectionUtil.getText(component.getModule(),component); if (text != null) { String binding = BindingProperty.suggestBindingFromText(component,text); if (binding != null && !result.contains(binding)) { result.add(binding); } } final String[] names = ArrayUtil.toStringArray(result); Arrays.sort(names); return names; }
private static boolean morphComponent(final GuiEditor editor,ComponentItem targetItem) { targetItem = InsertComponentProcessor.replaceAnyComponentItem(editor,targetItem,"Morph to Non-Palette Component"); if (targetItem == null) { return false; } final RadComponent newComponent = InsertComponentProcessor.createInsertedComponent(editor,targetItem); if (newComponent == null) return false; newComponent.setBinding(oldComponent.getBinding()); newComponent.setCustomLayoutConstraints(oldComponent.getCustomLayoutConstraints()); newComponent.getConstraints().restore(oldComponent.getConstraints()); updateBoundFieldType(editor,oldComponent,targetItem); final IProperty[] oldProperties = oldComponent.getModifiedProperties(); final Palette palette = Palette.getInstance(editor.getProject()); for(IProperty prop: oldProperties) { IntrospectedProperty newProp = palette.getIntrospectedProperty(newComponent,prop.getName()); if (newProp == null || !prop.getClass().equals(newProp.getClass())) continue; Object oldValue = prop.getPropertyValue(oldComponent); try { //noinspection unchecked newProp.setValue(newComponent,oldValue); } catch (Exception e) { // ignore } } retargetComponentProperties(editor,newComponent); final RadContainer parent = oldComponent.getParent(); int index = parent.indexOfComponent(oldComponent); parent.removeComponent(oldComponent); parent.addComponent(newComponent,index); newComponent.setSelected(true); if (oldComponent.isDefaultBinding()) { final String text = ForminspectionUtil.getText(newComponent.getModule(),newComponent); if (text != null) { String binding = BindingProperty.suggestBindingFromText(newComponent,text); if (binding != null) { new BindingProperty(newComponent.getProject()).setValueEx(newComponent,binding); } } newComponent.setDefaultBinding(true); } return true; }
private static String[] getFieldNames(final RadComponent component,text); if (binding != null && !result.contains(binding)) { result.add(binding); } } final String[] names = ArrayUtil.toStringArray(result); Arrays.sort(names); return names; }
private static boolean morphComponent(final GuiEditor editor,binding); } } newComponent.setDefaultBinding(true); } return true; }
private static boolean morphComponent(final GuiEditor editor,binding); } } newComponent.setDefaultBinding(true); } return true; }
关于openfire 用户认证多数据源配置 1 HybridUserPropertyProvider和opencloud 多认证中心的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于.properties文件中的PropertyPlaceholderConfigurer和环境变量、Big impact when set property type in-properly、com.hazelcast.config.properties.PropertyTypeConverter的实例源码、com.intellij.uiDesigner.propertyInspector.properties.BindingProperty的实例源码的相关信息,请在本站寻找。
本文标签: