/**
* Access a deep value inside a object
* Works by passing a path like "foo.bar", also works with nested arrays like "foo[0][1].baz"
* @author Victor B. https://gist.github.com/victornpb/4c7882c1b9d36292308e
* Unit tests: http://jsfiddle.net/Victornpb/0u1qygrh/
*/
function getDeepVal(obj, path) {
if (typeof obj === "undefined" || obj === null) return;
path = path.split(/[\.\[\]\"\']{1,2}/);
for (var i = 0, l = path.length; i < l; i++) {
if (path[i] === "") continue;
obj = obj[path[i]];
if (typeof obj === "undefined" || obj === null) return;
}
return obj;
}
Работает с
getDeepVal(obj,'foo.bar')
getDeepVal(obj,'foo.1.bar')
getDeepVal(obj,'foo[0].baz')
getDeepVal(obj,'foo[1][2]')
getDeepVal(obj,"foo['bar'].baz")
getDeepVal(obj,"foo['bar']['baz']")
getDeepVal(obj,"foo.bar.0.baz[1]['2']['w'].aaa[\"f\"].bb")
Что сказал erickson, но если вы все еще хотите это сделать, взгляните на Reflections . На своей странице:
Используя Reflections, вы можете запросить свои метаданные для:
blockquote>
- получить все подтипы некоторого типа
- получить все типы, аннотированные с некоторой аннотацией
- получить все типы, аннотированные с некоторой аннотацией, включая параметры аннотации, соответствующие
- , получить все методы, аннотированные с некоторыми
В общем, это дорого. Чтобы использовать отражение, класс должен быть загружен. Если вы хотите загрузить каждый класс, доступный в пути к классам, это потребует времени и памяти и не рекомендуется.
Если вы хотите этого избежать, вам нужно будет реализовать собственный анализатор файлов классов, который работает более эффективно, вместо отражения.
Механизм поставщика поставщика услуг является обычным средством для перечисления реализаций подключаемой услуги. Используйте ServiceLoader
в Java 6 или реализуйте свои собственные в более ранних версиях. Я представил пример в другом ответе.
Весна имеет довольно простой способ достичь этого:
public interface ITask {
void doStuff();
}
@Component
public class MyTask implements ITask {
public void doStuff(){}
}
Затем вы можете автоувеличивать список типов ITask
, а Spring будет заполнять его всеми реализациями:
@Service
public class TaskService {
@Autowired
private List<ITask> tasks;
}
Я искал какое-то время, и, похоже, существуют разные подходы, вот резюме:
Reflections reflections = new Reflections("firstdeveloper.examples.reflections");
Set<Class<? extends Pet>> classes = reflections.getSubTypesOf(Pet.class);
ServiceLoader<Pet> loader = ServiceLoader.load(Pet.class);
for (Pet implClass : loader) {
System.out.println(implClass.getClass().getSimpleName()); // prints Dog, Cat
}
Обратите внимание, что для этого вам нужно определить Pet
как ServiceProviderInterface ( SPI) и объявить о его реализации. вы делаете это, создавая файл в resources/META-INF/services
с именем examples.reflections.Pet
и объявляя все реализации Pet
в нем examples.reflections.Dog
examples.reflections.Cat
Package[] packages = Package.getPackages();
for (Package p : packages) {
MyPackageAnnotation annotation = p.getAnnotation(MyPackageAnnotation.class);
if (annotation != null) {
Class<?>[] implementations = annotation.implementationsOfPet();
for (Class<?> impl : implementations) {
System.out.println(impl.getSimpleName());
}
}
}
и определение аннотации: @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PACKAGE)
public @interface MyPackageAnnotation {
Class<?>[] implementationsOfPet() default {};
}
, и вы должны объявить аннотацию на уровне пакета в файле с именем package-info.java
внутри этого пакета. Вот пример содержимого: @MyPackageAnnotation(implementationsOfPet = {Dog.class, Cat.class})
package examples.reflections;
Обратите внимание, что только пакеты, известные в ClassLoader в это время, будут загружены вызовом Package.getPackages()
. Кроме того, существуют другие подходы основанный на URLClassLoader, который всегда будет ограничен уже загруженными классами, если вы не выполняете поиск по каталогам.
Попробуйте ClassGraph . (Отказ от ответственности, я автор). ClassGraph поддерживает сканирование для классов, которые реализуют данный интерфейс, либо во время выполнения, либо во время сборки, но и многое другое. ClassGraph может создавать абстрактное представление всего графа классов (все классы, аннотации, методы, параметры метода и поля) в памяти, для всех классов в пути к классам или для классов в белых списках, и вы можете запросить этот графа классов, однако вы хотите. ClassGraph поддерживает больше механизмов спецификации классов и загрузчиков классов , чем любой другой сканер, а также легко работает с новой системой модулей JPMS, поэтому, если вы основываете свой код на ClassGraph, ваш код будет максимально переносимым. См. здесь API.
Я столкнулся с тем же вопросом. Мое решение состояло в том, чтобы использовать рефлексию для изучения всех методов класса ObjectFactory, исключая те методы, которые не были createXXX (), возвращающие экземпляр одного из моих связанных POJO. Каждый обнаруженный класс добавляется в массив Class [], который затем передается в экземплярный вызов JAXBContext. Это хорошо работает, нужно только загрузить класс ObjectFactory, который все равно понадобился. Мне нужно только поддерживать класс ObjectFactory, задачу, выполняемую вручную (в моем случае, потому что я начал с POJO и использовал схему), или может быть сгенерирован по необходимости xjc. В любом случае, он эффективен, прост и эффективен.
Кроме того, если вы пишете плагин IDE (где то, что вы пытаетесь сделать, является относительно общим), тогда IDE обычно предлагает вам более эффективные способы доступа к иерархии классов текущего состояния кода пользователя.
Что эриксон сказал лучше всего. Вот связанный вопрос и ответ нить - http://www.velocityreviews.com/forums/t137693-find-all-implementing-classes-in-classpath.html
Библиотека Apache BCEL позволяет вам читать классы без их загрузки. Я считаю, что это будет быстрее, потому что вы сможете пропустить этап проверки. Другая проблема с загрузкой всех классов с помощью загрузчика классов заключается в том, что вы будете испытывать огромное влияние на память, а также непреднамеренно запускать любые статические блоки кода, которые вы, вероятно, не хотите делать.
Ссылка на библиотеку Apache BCEL - http://jakarta.apache.org/bcel/
Да, первым шагом является определение «всех» классов, о которых вы заботитесь. Если у вас уже есть эта информация, вы можете перечислить каждую из них и использовать instanceof для проверки отношения. Связанная статья находится здесь: http://www.javaworld.com/javaworld/javatips/jw-javatip113.html
new Reflections("my.package").getSubTypesOf(MyInterface.class)
– zapp 16 March 2013 в 15:12