调整 return 方法的值,该方法是单例且具有最终访问修饰符
Adjust return value of a method which is a singleton and has final access modifiers
我想从实例 class 调整方法的 return 值,我不太确定是否可以使用或不使用反射。我想不通,所以我想在这里问一下。假设我有以下 class Foo:
public final class Foo {
private static final INSTANCE = new Foo()
protected Foo() {}
public final String getName() {
return "Foo";
}
public static Foo getInstance() {
return INSTANCE;
}
}
一些上下文:
- Foo class 来自外部库
- Foo class 不可调整
- Foo class 不可扩展
因此,对于这个基本示例,我想从方法 getName() 中获取 Bar returned 而不是 Foo.非常明确:
Foo foo = Foo.getInstance();
String name = foo.getName();
System.out.println(name) // --> prints "Bar"
我为什么需要这个?
好吧,我需要将这个 Foo 实例传递给另一个只接受 Foo 类型对象的方法。此方法将调用方法 getName() 并将进行一些额外的计算。
实际用例:
我会尝试提供更多背景信息,希望它会更清楚一些。构建器 class 中有一个方法接受 KeyManagerFactory
的实例,该方法称为 setKeyManagerFactory(KeyManagerFactory keyManagerFactory)
。此构建器 class 将在 KeyManagerFactory 上内部调用 getKeyManagers
并且它将 return KeyManagers[]
KeyManagerFactory 是最终的 class,它根本没有 public 构造函数。 getKeyManager 方法也是最终的。我已经有一个 KeyManager[]
,所以我想将此 KeyManagerFactory 破解为 return 我自己的数组拥有的 KeyManagers,并将其提供给构建器。
通常 KeyManagerFactory 使用以下代码片段实例化:
KeyStore keyStore = ... //initialized keyStore
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
kmf.init(keyStore, keyPassword);
KeyManager[] keyManagers = kmf.getKeyManagers();
通过上面的代码片段,KeyManagerFactory 将 return 一个基于提供的 KeyStore 对象的 KeyManager 数组。我想要实现的是以某种方式 return 我的自定义 KeyManager 数组。
我还添加了KeyManagerFactory的反编译源代码:
package javax.net.ssl;
import java.security.AccessController;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivilegedAction;
import java.security.Provider;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import sun.security.jca.GetInstance;
import sun.security.jca.GetInstance.Instance;
public class KeyManagerFactory {
private Provider provider;
private KeyManagerFactorySpi factorySpi;
private String algorithm;
public static final String getDefaultAlgorithm() {
String var0 = (String)AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return Security.getProperty("ssl.KeyManagerFactory.algorithm");
}
});
if (var0 == null) {
var0 = "SunX509";
}
return var0;
}
protected KeyManagerFactory(KeyManagerFactorySpi var1, Provider var2, String var3) {
this.factorySpi = var1;
this.provider = var2;
this.algorithm = var3;
}
public final String getAlgorithm() {
return this.algorithm;
}
public static final KeyManagerFactory getInstance(String var0) throws NoSuchAlgorithmException {
Instance var1 = GetInstance.getInstance("KeyManagerFactory", KeyManagerFactorySpi.class, var0);
return new KeyManagerFactory((KeyManagerFactorySpi)var1.impl, var1.provider, var0);
}
public static final KeyManagerFactory getInstance(String var0, String var1) throws NoSuchAlgorithmException, NoSuchProviderException {
Instance var2 = GetInstance.getInstance("KeyManagerFactory", KeyManagerFactorySpi.class, var0, var1);
return new KeyManagerFactory((KeyManagerFactorySpi)var2.impl, var2.provider, var0);
}
public static final KeyManagerFactory getInstance(String var0, Provider var1) throws NoSuchAlgorithmException {
Instance var2 = GetInstance.getInstance("KeyManagerFactory", KeyManagerFactorySpi.class, var0, var1);
return new KeyManagerFactory((KeyManagerFactorySpi)var2.impl, var2.provider, var0);
}
public final Provider getProvider() {
return this.provider;
}
public final void init(KeyStore var1, char[] var2) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
this.factorySpi.engineInit(var1, var2);
}
public final void init(ManagerFactoryParameters var1) throws InvalidAlgorithmParameterException {
this.factorySpi.engineInit(var1);
}
public final KeyManager[] getKeyManagers() {
return this.factorySpi.engineGetKeyManagers();
}
}
你可以这样做。 (您可以对私有字段使用 setAccessible(true))
public final class Single {
public String s;
public Single() {
}
public String getS() {
return s;
}
}
public class Main {
public static void main(String[] args) throws IllegalAccessException {
Single single = new Single();
single.getClass().getFields()[0].set(single, "Hmm");
System.out.println(single.getS());
}
}
在@tgdavies 的提示下,我能够完成我想要的。谢谢!
所以我所做的是创建了一个 KeyManagerFactoryWrapper
,其中包含一个名为 KeyManagerFactorySpiWrapper
的自定义 KeyManagerFactorySpi
。
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.KeyManagerFactorySpi;
import javax.net.ssl.ManagerFactoryParameters;
import java.security.KeyStore;
import java.security.Provider;
/**
* @author Hakan Altindag
*/
public class KeyManagerFactoryWrapper extends KeyManagerFactory {
private static final String KEY_MANAGER_FACTORY_ALGORITHM = "no-algorithm";
private static final Provider PROVIDER = new Provider("", 1.0, "") {};
public KeyManagerFactoryWrapper(KeyManager keyManager) {
super(new KeyManagerFactorySpiWrapper(keyManager), PROVIDER, KEY_MANAGER_FACTORY_ALGORITHM);
}
private static class KeyManagerFactorySpiWrapper extends KeyManagerFactorySpi {
private final KeyManager[] keyManagers;
public KeyManagerFactorySpiWrapper(KeyManager keyManager) {
this.keyManagers = new KeyManager[]{keyManager};
}
@Override
protected void engineInit(KeyStore keyStore, char[] keyStorePassword) {
// ignoring
}
@Override
protected void engineInit(ManagerFactoryParameters managerFactoryParameters) {
// ignoring
}
@Override
protected KeyManager[] engineGetKeyManagers() {
return keyManagers;
}
}
}
我能够通过 TrustManagerFactory 实现同样的效果:
import javax.net.ssl.ManagerFactoryParameters;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.TrustManagerFactorySpi;
import java.security.KeyStore;
import java.security.Provider;
/**
* @author Hakan Altindag
*/
public class TrustManagerFactoryWrapper extends TrustManagerFactory {
private static final String KEY_MANAGER_FACTORY_ALGORITHM = "no-algorithm";
private static final Provider PROVIDER = new Provider("", 1.0, "") {};
public TrustManagerFactoryWrapper(TrustManager trustManager) {
super(new TrustManagerFactorySpiWrapper(trustManager), PROVIDER, KEY_MANAGER_FACTORY_ALGORITHM);
}
private static class TrustManagerFactorySpiWrapper extends TrustManagerFactorySpi {
private final TrustManager[] trustManagers;
public TrustManagerFactorySpiWrapper(TrustManager trustManager) {
this.trustManagers = new TrustManager[]{trustManager};
}
@Override
protected void engineInit(KeyStore keyStore) {
// ignoring
}
@Override
protected void engineInit(ManagerFactoryParameters managerFactoryParameters) {
// ignoring
}
@Override
protected TrustManager[] engineGetTrustManagers() {
return trustManagers;
}
}
}
现在我可以使用以下代码片段轻松创建 KeyManagerFactory 和 TrustManagerFactory:
KeyManager keyManager = ...; //initialised keyManager
TrustManager trustManager = ...; //initialised trustManager
KeyManagerFactory = new KeyManagerFactoryWrapper(keyManager);
TrustManagerFactory = new TrustManagerFactoryWrapper(keyManager);
我想从实例 class 调整方法的 return 值,我不太确定是否可以使用或不使用反射。我想不通,所以我想在这里问一下。假设我有以下 class Foo:
public final class Foo {
private static final INSTANCE = new Foo()
protected Foo() {}
public final String getName() {
return "Foo";
}
public static Foo getInstance() {
return INSTANCE;
}
}
一些上下文:
- Foo class 来自外部库
- Foo class 不可调整
- Foo class 不可扩展
因此,对于这个基本示例,我想从方法 getName() 中获取 Bar returned 而不是 Foo.非常明确:
Foo foo = Foo.getInstance();
String name = foo.getName();
System.out.println(name) // --> prints "Bar"
我为什么需要这个?
好吧,我需要将这个 Foo 实例传递给另一个只接受 Foo 类型对象的方法。此方法将调用方法 getName() 并将进行一些额外的计算。
实际用例:
我会尝试提供更多背景信息,希望它会更清楚一些。构建器 class 中有一个方法接受 KeyManagerFactory
的实例,该方法称为 setKeyManagerFactory(KeyManagerFactory keyManagerFactory)
。此构建器 class 将在 KeyManagerFactory 上内部调用 getKeyManagers
并且它将 return KeyManagers[]
KeyManagerFactory 是最终的 class,它根本没有 public 构造函数。 getKeyManager 方法也是最终的。我已经有一个 KeyManager[]
,所以我想将此 KeyManagerFactory 破解为 return 我自己的数组拥有的 KeyManagers,并将其提供给构建器。
通常 KeyManagerFactory 使用以下代码片段实例化:
KeyStore keyStore = ... //initialized keyStore
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
kmf.init(keyStore, keyPassword);
KeyManager[] keyManagers = kmf.getKeyManagers();
通过上面的代码片段,KeyManagerFactory 将 return 一个基于提供的 KeyStore 对象的 KeyManager 数组。我想要实现的是以某种方式 return 我的自定义 KeyManager 数组。
我还添加了KeyManagerFactory的反编译源代码:
package javax.net.ssl;
import java.security.AccessController;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivilegedAction;
import java.security.Provider;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import sun.security.jca.GetInstance;
import sun.security.jca.GetInstance.Instance;
public class KeyManagerFactory {
private Provider provider;
private KeyManagerFactorySpi factorySpi;
private String algorithm;
public static final String getDefaultAlgorithm() {
String var0 = (String)AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return Security.getProperty("ssl.KeyManagerFactory.algorithm");
}
});
if (var0 == null) {
var0 = "SunX509";
}
return var0;
}
protected KeyManagerFactory(KeyManagerFactorySpi var1, Provider var2, String var3) {
this.factorySpi = var1;
this.provider = var2;
this.algorithm = var3;
}
public final String getAlgorithm() {
return this.algorithm;
}
public static final KeyManagerFactory getInstance(String var0) throws NoSuchAlgorithmException {
Instance var1 = GetInstance.getInstance("KeyManagerFactory", KeyManagerFactorySpi.class, var0);
return new KeyManagerFactory((KeyManagerFactorySpi)var1.impl, var1.provider, var0);
}
public static final KeyManagerFactory getInstance(String var0, String var1) throws NoSuchAlgorithmException, NoSuchProviderException {
Instance var2 = GetInstance.getInstance("KeyManagerFactory", KeyManagerFactorySpi.class, var0, var1);
return new KeyManagerFactory((KeyManagerFactorySpi)var2.impl, var2.provider, var0);
}
public static final KeyManagerFactory getInstance(String var0, Provider var1) throws NoSuchAlgorithmException {
Instance var2 = GetInstance.getInstance("KeyManagerFactory", KeyManagerFactorySpi.class, var0, var1);
return new KeyManagerFactory((KeyManagerFactorySpi)var2.impl, var2.provider, var0);
}
public final Provider getProvider() {
return this.provider;
}
public final void init(KeyStore var1, char[] var2) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
this.factorySpi.engineInit(var1, var2);
}
public final void init(ManagerFactoryParameters var1) throws InvalidAlgorithmParameterException {
this.factorySpi.engineInit(var1);
}
public final KeyManager[] getKeyManagers() {
return this.factorySpi.engineGetKeyManagers();
}
}
你可以这样做。 (您可以对私有字段使用 setAccessible(true))
public final class Single {
public String s;
public Single() {
}
public String getS() {
return s;
}
}
public class Main {
public static void main(String[] args) throws IllegalAccessException {
Single single = new Single();
single.getClass().getFields()[0].set(single, "Hmm");
System.out.println(single.getS());
}
}
在@tgdavies 的提示下,我能够完成我想要的。谢谢!
所以我所做的是创建了一个 KeyManagerFactoryWrapper
,其中包含一个名为 KeyManagerFactorySpiWrapper
的自定义 KeyManagerFactorySpi
。
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.KeyManagerFactorySpi;
import javax.net.ssl.ManagerFactoryParameters;
import java.security.KeyStore;
import java.security.Provider;
/**
* @author Hakan Altindag
*/
public class KeyManagerFactoryWrapper extends KeyManagerFactory {
private static final String KEY_MANAGER_FACTORY_ALGORITHM = "no-algorithm";
private static final Provider PROVIDER = new Provider("", 1.0, "") {};
public KeyManagerFactoryWrapper(KeyManager keyManager) {
super(new KeyManagerFactorySpiWrapper(keyManager), PROVIDER, KEY_MANAGER_FACTORY_ALGORITHM);
}
private static class KeyManagerFactorySpiWrapper extends KeyManagerFactorySpi {
private final KeyManager[] keyManagers;
public KeyManagerFactorySpiWrapper(KeyManager keyManager) {
this.keyManagers = new KeyManager[]{keyManager};
}
@Override
protected void engineInit(KeyStore keyStore, char[] keyStorePassword) {
// ignoring
}
@Override
protected void engineInit(ManagerFactoryParameters managerFactoryParameters) {
// ignoring
}
@Override
protected KeyManager[] engineGetKeyManagers() {
return keyManagers;
}
}
}
我能够通过 TrustManagerFactory 实现同样的效果:
import javax.net.ssl.ManagerFactoryParameters;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.TrustManagerFactorySpi;
import java.security.KeyStore;
import java.security.Provider;
/**
* @author Hakan Altindag
*/
public class TrustManagerFactoryWrapper extends TrustManagerFactory {
private static final String KEY_MANAGER_FACTORY_ALGORITHM = "no-algorithm";
private static final Provider PROVIDER = new Provider("", 1.0, "") {};
public TrustManagerFactoryWrapper(TrustManager trustManager) {
super(new TrustManagerFactorySpiWrapper(trustManager), PROVIDER, KEY_MANAGER_FACTORY_ALGORITHM);
}
private static class TrustManagerFactorySpiWrapper extends TrustManagerFactorySpi {
private final TrustManager[] trustManagers;
public TrustManagerFactorySpiWrapper(TrustManager trustManager) {
this.trustManagers = new TrustManager[]{trustManager};
}
@Override
protected void engineInit(KeyStore keyStore) {
// ignoring
}
@Override
protected void engineInit(ManagerFactoryParameters managerFactoryParameters) {
// ignoring
}
@Override
protected TrustManager[] engineGetTrustManagers() {
return trustManagers;
}
}
}
现在我可以使用以下代码片段轻松创建 KeyManagerFactory 和 TrustManagerFactory:
KeyManager keyManager = ...; //initialised keyManager
TrustManager trustManager = ...; //initialised trustManager
KeyManagerFactory = new KeyManagerFactoryWrapper(keyManager);
TrustManagerFactory = new TrustManagerFactoryWrapper(keyManager);