我正在通过反射API,但无法在实时应用程序中使用实时场景/用例中的反射来创建对象。有没有人使用反射来创建使用反射和用例的对象?
答案 0 :(得分:2)
以下是几个用例:
1)如果您希望实现的灵活性并且不想使用依赖注入框架,则可以使用在启动应用程序时定义的系统属性来指定要使用的实现类。 JAXP为此使用了许多系统属性,例如javax.xml.parsers.DocumentBuilderFactory。
例如,如果你有一个名为AutoRideService的接口/抽象类,并希望能够配置在运行时使用的实现,你可以这样得到它:
private static AutoRideService lookupAutoRideService() {
String className = System.getProperty("autorideservice.classname");
try {
@SuppressWarnings("unchecked")
Class<AutoRideService> clazz = (Class<AutoRideService>) Class.forName(className);
return clazz.newInstance();
} catch (Exception ex) {
throw new IllegalStateException("Failed to lookup auto ride service using class name: " + className, ex);
}
}
2)如果您需要在同一程序中使用不同且不兼容的类版本。在这里,您可以使用多个类加载器和反射。
例如,我有一些存储在数据库中的Oauth令牌,它们是由旧版本的Spring Security Oauth2创建的。我想升级Spring Security Oauth2的版本和存储的令牌,但新版本对反序列化令牌所需的类进行了重大且向后的不兼容更改。以下是一段代码:
/**
* This takes serialization data of the old authentication object and then
* reads it as an object using a separate class loader which has the old version of the spring and spring security classes
* We then use reflection to access the compatible fields and then use this data to construct the new class version object
* @param oldAuthData The serialized data created with the old version of the classes
* @return The deserialized OAuth2Authentication object constructed with the new class versions
* @throws IOException
* @throws ClassNotFoundException
* @throws NoSuchMethodException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
private OAuth2Authentication deserializeOAuth2Authentication(byte[] oldAuthData) throws IOException, ClassNotFoundException, NoSuchMethodException,
IllegalAccessException, InvocationTargetException {
OAuth2Authentication auth = null;
ObjectInputStream ois = new CustomObjectInputStream(new ByteArrayInputStream(oldAuthData), this.deserialisationClassLoader);
try {
Object obj = ois.readObject();
// the instance of this is the old OAuth2Authentication however we cannot cast
// so have to use reflection to access the fields and data
// and then construct a new OAuth2Authentication from this
Object oldAuthorizationRequest = MethodUtils.invokeMethod(obj, "getAuthorizationRequest", NO_ARGS);
Object authentication = MethodUtils.invokeMethod(obj, "getUserAuthentication", NO_ARGS);
Object principal = MethodUtils.invokeMethod(authentication, "getPrincipal", NO_ARGS);
Object credentials = MethodUtils.invokeMethod(authentication, "getCredentials", NO_ARGS);
Collection<GrantedAuthority> authorities = convertAuthorities((Collection<?>) MethodUtils.invokeMethod(authentication, "getAuthorities", NO_ARGS));
// now construct the oauth authentication object with the new auth and request
Authentication authToken = new UsernamePasswordAuthenticationToken(principal, credentials, authorities);
AuthorizationRequest authReq = convertAuthorizationRequest(oldAuthorizationRequest);
auth = new OAuth2Authentication(authReq, authToken);
} finally {
ois.close();
}
return auth;
}