Java Reflection : Java 클래스의 모든 getter 메서드를 가져 와서 호출하는 방법
많은 getter가있는 Java 클래스를 작성합니다. 이제 모든 getter 메서드를 가져 와서 언젠가 호출하고 싶습니다. getMethods () 또는 getMethod (String name, Class ... parameterTypes)와 같은 메서드가 있다는 것을 알고 있지만 실제로 getter를 얻고 싶습니다 ..., regex를 사용합니까? 누구든지 말해 줄 수 있나요? 감사합니다!
정규식을 사용하지 말고 다음을 사용하십시오 Introspector.
for(PropertyDescriptor propertyDescriptor :
Introspector.getBeanInfo(yourClass).getPropertyDescriptors()){
// propertyEditor.getReadMethod() exposes the getter
// btw, this may be null if you have a write-only property
System.out.println(propertyDescriptor.getReadMethod());
}
일반적으로 Object.class의 속성을 원하지 않으므로 두 개의 매개 변수와 함께 메서드를 사용합니다.
Introspector.getBeanInfo(yourClass, stopClass)
// usually with Object.class as 2nd param
// the first class is inclusive, the second exclusive
BTW :이를 수행하고 높은 수준의보기를 제공하는 프레임 워크가 있습니다. 예를 들어 commons / beanutils에는 방법이 있습니다.
Map<String, String> properties = BeanUtils.describe(yourObject);
( docs here ) 모든 게터를 찾아 실행하고 결과를지도에 저장합니다. 불행히도 BeanUtils.describe()반환하기 전에 모든 속성 값을 문자열로 변환합니다. WTF. 감사합니다 @danw
최신 정보:
다음 Map<String, Object>은 객체의 빈 속성을 기반으로 를 반환하는 Java 8 메서드입니다 .
public static Map<String, Object> beanProperties(Object bean) {
try {
return Arrays.asList(
Introspector.getBeanInfo(bean.getClass(), Object.class)
.getPropertyDescriptors()
)
.stream()
// filter out properties with setters only
.filter(pd -> Objects.nonNull(pd.getReadMethod()))
.collect(Collectors.toMap(
// bean property name
PropertyDescriptor::getName,
pd -> { // invoke method to get value
try {
return pd.getReadMethod().invoke(bean);
} catch (Exception e) {
// replace this with better error handling
return null;
}
}));
} catch (IntrospectionException e) {
// and this, too
return Collections.emptyMap();
}
}
그래도 오류 처리를 더 강력하게 만들고 싶을 것입니다. 상용구에 대해 죄송합니다. 확인 된 예외로 인해 여기에서 제대로 작동하지 않습니다.
Collectors.toMap ()은 null 값을 싫어합니다. 다음은 위 코드의 더 명령적인 버전입니다.
public static Map<String, Object> beanProperties(Object bean) {
try {
Map<String, Object> map = new HashMap<>();
Arrays.asList(Introspector.getBeanInfo(bean.getClass(), Object.class)
.getPropertyDescriptors())
.stream()
// filter out properties with setters only
.filter(pd -> Objects.nonNull(pd.getReadMethod()))
.forEach(pd -> { // invoke method to get value
try {
Object value = pd.getReadMethod().invoke(bean);
if (value != null) {
map.put(pd.getName(), value);
}
} catch (Exception e) {
// add proper error handling here
}
});
return map;
} catch (IntrospectionException e) {
// and here, too
return Collections.emptyMap();
}
}
JavaSlang을 사용하여 더 간결하게 동일한 기능을 제공합니다 .
public static Map<String, Object> javaSlangBeanProperties(Object bean) {
try {
return Stream.of(Introspector.getBeanInfo(bean.getClass(), Object.class)
.getPropertyDescriptors())
.filter(pd -> pd.getReadMethod() != null)
.toJavaMap(pd -> {
try {
return new Tuple2<>(
pd.getName(),
pd.getReadMethod().invoke(bean));
} catch (Exception e) {
throw new IllegalStateException();
}
});
} catch (IntrospectionException e) {
throw new IllegalStateException();
}
}
그리고 여기 Guava 버전이 있습니다.
public static Map<String, Object> guavaBeanProperties(Object bean) {
Object NULL = new Object();
try {
return Maps.transformValues(
Arrays.stream(
Introspector.getBeanInfo(bean.getClass(), Object.class)
.getPropertyDescriptors())
.filter(pd -> Objects.nonNull(pd.getReadMethod()))
.collect(ImmutableMap::<String, Object>builder,
(builder, pd) -> {
try {
Object result = pd.getReadMethod()
.invoke(bean);
builder.put(pd.getName(),
firstNonNull(result, NULL));
} catch (Exception e) {
throw propagate(e);
}
},
(left, right) -> left.putAll(right.build()))
.build(), v -> v == NULL ? null : v);
} catch (IntrospectionException e) {
throw propagate(e);
}
}
이를 위해 Reflections 프레임 워크를 사용할 수 있습니다.
import org.reflections.ReflectionUtils.*;
Set<Method> getters = ReflectionUtils.getAllMethods(someClass,
ReflectionUtils.withModifier(Modifier.PUBLIC), ReflectionUtils.withPrefix("get"));
// Get the Class object associated with this class.
MyClass myClass= new MyClass ();
Class objClass= myClass.getClass();
// Get the public methods associated with this class.
Method[] methods = objClass.getMethods();
for (Method method:methods)
{
System.out.println("Public method found: " + method.toString());
}
Spring offers an easy BeanUtil method for Bean introspection:
PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(clazz, property);
Method getter = pd.getReadMethod();
This code is tested OK.
private void callAllGetterMethodsInTestModel(TestModel testModelObject) {
try {
Class testModelClass = Class.forName("com.example.testreflectionapi.TestModel");
Method[] methods = testModelClass.getDeclaredMethods();
ArrayList<String> getterResults = new ArrayList<>();
for (Method method :
methods) {
if (method.getName().startsWith("get")){
getterResults.add((String) method.invoke(testModelObject));
}
}
Log.d("sayanReflextion", "==>: "+getterResults.toString());
} catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
You should maintain a generic getter in every bean, so that to invoke getAttribute1() you should be able to invoke a generic getter get("Attribute1")
This generic getter will in-turn invoke the correct getter
Object get(String attribute)
{
if("Attribute1".equals(attribute)
{
return getAttribute1();
}
}
This approach involves you to maintain this separate list in every bean but this way you avoid reflection which has performance issues, so if you writing production code which needs to have good performance you can use the above pattern for all your beans.
If it is some test code or utility code which does not have high performance requirements then you are better off taking other approaches since this approach is error prone unless you can write some kind of compile time checker that ensures this generic getter function works for all attributes.
'Program Club' 카테고리의 다른 글
| Bash를 사용하여 한 디렉토리를 다른 디렉토리로 어떻게 병합합니까? (0) | 2020.11.06 |
|---|---|
| 원격 컴퓨터에서 MySQL 덤프를 사용하는 방법 (0) | 2020.11.06 |
| PHP Try Catch 블록에서 예외 발생 (0) | 2020.11.06 |
| 모바일 웹에서 핀치 줌 비활성화 (0) | 2020.11.06 |
| 설정되지 않은 경우에만 Ant 속성을 설정하는 방법 (0) | 2020.11.06 |