我正在使用反射API,但无法在实时应用程序中使用实时场景/用例创建对象。有人使用反射来创建对象吗?在哪个用例中?
下面是几个用例:
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;
}