目前我有一个LDAP管理系统,它使用Spring LDAP连接到LDAP服务器并对其进行管理;但是,如果我想要更改为其他服务器,我必须关闭系统,更改配置设置,然后重新启动它。如果我只需要一个允许我在不同服务器之间交换的下拉列表就会简单得多。
正因为如此,我正在调查动态设置Context Source的可能性。我找到了Incorrect injection between beans,答案看起来就像我希望能够完成的那样。但是,我的系统不使用DAO,而是使用LdapRepository来管理用户。
我的问题是:我如何更改Spring使用的ContextSource在运行时与LdapRepository类交互而不是在xml文件中设置,同时尽可能地保留我当前的项目结构?
我不想将所有内容转换为使用DAO,而是将此功能与现有代码配合使用。
编辑:也应该提到我让Spring引导存储库的实现。
答案 0 :(得分:0)
我发现SO上的其他post(与您的问题没有直接关系)显示了如何在会话中确定LDAPTemplate
的范围。
在不了解更多资料的情况下,我无法确定此解决方案是否适合您,但我认为值得尝试。
您应该在会话中声明LDAPTemplate范围:
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate"
p:contextSource_ref="contextSource" scope="session">
<aop:scope-proxy/>
</bean>
您应该尝试将其作为LDAPOperation注入LDAPRepository类,以允许Spring AOP使用JDK代理。如果不可能,则应将Spring AOP配置为<aop:scope-proxy proxy-target-class="true"/>
在您想要更改ContextSource
的地方,请注入LDAPTemplate
。如果您可以使用JDK Proxies,请将其注入LDAPOperation
以获取范围代理。您应该能够通过Spring AOP代理实现的LDAPTemplate
接口获得正确的Advised
:
LDAPOperation ldapOperation;
...
LDAPTemplate ldapTemplate = (LDAPTemplate) ((Advised)ldapOperation)
.getTargetSource().getTarget();
ldapTemplate.setContextSource(newContextSource);
以下是访问Spring AOP代理目标的参考资料:来自Tech Per的 How To Acess Target Object Behind a Spring Proxy
答案 1 :(得分:0)
这是一个角落。该库实际上并不是为此而设计的,但我认为实现您尝试做的最简单的方法是实现一个自定义委托ContextSource
,它保留对您想要的所有不同实际ContextSource的引用。能够使用,例如:
public class SessionBasedDelegatingContextSource implements ContextSource {
private Map<String, ContextSource> contextSources;
@Required
public void setContextSources(Map<String, ContextSource> contextSources) {
this.contextSources = new HashMap<>(contextSources);
}
protected final ContextSource getSessionContextSource() {
String id = (String) RequestContextHolder.currentRequestAttributes()
.getAttribute("currentContextSource", SCOPE_SESSION);
if(id == null) {
throw new IllegalStateException("No Ldap target selected");
}
ContextSource contextSource = contextSources.get(id);
if(contextSource == null) {
throw new IllegalArgumentException("No Ldap target selected");
}
return contextSource;
}
@Override
public DirContext getReadOnlyContext() {
getSessionContextSource().getReadOnlyContext();
}
@Override
public DirContext getReadWriteContext() {
getSessionContextSource().getReadWriteContext();
}
@Override
public DirContext getContext(String principal, String credentials) {
getSessionContextSource().getContext(principal, credentials);
}
}
现在,如果您注册RequestContextFilter,请声明所有不同的ContextSource,将它们注入SessionBasedDelegatingContextSource
,并将其用作存储库的ContextSource(即您定义的LdapTemplate使用的ContextSource) ,你需要做的就是在会话中放入一个合适的ContextSource标识符,你应该没问题。