Tuz 轻量级资源容器
Внимание:
v1.0 и 0.8.0-FINAL и ниже версии не совместимы! API был немного скорректирован, были удалены лишние функции, была скорректирована архитектура классов. Пожалуйста, используйте v1.0 или более поздние версии!
Контейнер управления ресурсами: ресурсы загружаются в память в виде пар «ключ-значение», что упрощает их использование.
Прозрачный контейнер ресурсов: тот же способ использования, другой загрузчик, позволяет достичь прозрачности использования ресурсов.
Лёгкий контейнер внедрения зависимостей: классы реализации объектов напрямую внедряются в ссылки на объекты, что позволяет отделить бизнес-логику.
Контейнера перехвата методов объекта: динамический прокси используется для перехватчиков методов, что позволяет разделить бизнес-логику на основную и второстепенную.
Набор инструментов для операций ввода-вывода: предоставляет распространённые методы ввода-вывода, упрощая работу с вводом-выводом.
Tuz — это облегчённый менеджер ресурсов, который помогает управлять вашими ресурсами, такими как файлы .properties и JSON. После загрузки они доступны везде, и их использование очень просто!
Он также поддерживает прозрачную загрузку и работу с ресурсами Redis.
Вы можете легко расширить его функциональность, просто реализовав несколько интерфейсов!
Встроенные плагины внедрения зависимостей позволяют легко отделять интерфейсы от классов реализации и обеспечивают элегантное программирование!
Мы будем добавлять больше функций и плагинов для управления ресурсами в будущем!
Tuz — небольшой менеджер ресурсов. Например, вы можете загрузить некоторые файлы .properties и использовать их повсюду! Вы можете расширить его, реализовав некоторые интерфейсы! Также я подготовил такие строительные плагины, как DiPlugin. Со временем он будет становиться всё лучше и лучше!
Официальный сайт Tuz: http://www.fishgoddess.cn/tuz/
Контакты: fishgoddess@qq.com
Открытый исходный код: Apache License 2.0
Если вы используете Maven-проект, то всё становится проще, вам нужно только добавить несколько строк в ваш pom.xml:
<!-- https://mvnrepository.com/artifact/cn.com.fishin/Tuz -->
<dependency>
<groupId>cn.com.fishin</groupId>
<artifactId>Tuz</artifactId>
<version>1.0-FINAL</version>
</dependency>
Конечно, вы также можете использовать Gradle-проект, тогда вам нужно сделать то же самое, что и в Maven-проекте:
// https://mvnrepository.com/artifact/cn.com.fishin/Tuz
compile group: 'cn.com.fishin', name: 'Tuz', version: '1.0-FINAL'
Для других инструментов сборки или репозиториев см. информацию в Maven Central. Если вы не знаете, какой URL использовать, нажмите на значок Maven Central выше или перейдите по этой ссылке: [https://mvnrepository.com/artifact/cn.com.fishin/Tuz].
Дополнительную информацию можно найти на этом веб-сайте: [https://mvnrepository.com/artifact/cn.com.fishin/Tuz].
Или вы используете обычный Java-проект и вам нужно вручную импортировать библиотеку. Мы рекомендуем перейти на Maven-проект. Если вы не хотите переключаться, вы можете скачать JAR-файл нужной вам версии, а также документацию и исходный код с GitHub: Tuz - GitHub.
Мы предоставляем две версии JAR: одну без зависимостей, другую с полными зависимостями. Выберите одну из них для загрузки.
Или, что ещё хуже, вы используете традиционный Java-проект с добавлением JAR вручную, тогда вы должны изменить свой способ разработки или загрузить JAR с GitHub: Tuz - GitHub. Мы предоставляем две версии jar, одна маленькая, но не полная, другая полная, но не маленькая. Вы должны выбрать одну из них. ``` //Tuz.reLoad(new ClasspathPropertiesLoader("test.properties", "test"));
// 如果你不再需要这个资源文件,就调用这个方法
// 注意这里的 new ClasspathPropertiesLoader("test.properties", "test") 应该要和上面 load 的一致
//Tuz.unLoad(new ClasspathPropertiesLoader("test.properties", "test"));
}
#### 2. Простой способ внедрения зависимостей
```java
// 参考 test 文件夹下的 cn.com.fishin.demo.TuzSimpleDemo
public class TuzSimpleDemo2 {
public static void main(String[] args) throws Throwable {
// Традиционный способ использования интерфейса:
//xxxService service = new xxxServiceImpl();
// Этот способ не обеспечивает реального разделения, использование Spring и подобных фреймворков может обеспечить разделение, но требует введения большого количества фреймворк-кода
// А с помощью Tuz можно легко добиться разделения, см. ниже:
Tuz tuz = Tuz.instance();
tuz.load(new ClasspathPropertiesLoader("test.properties", "test"));
// Непосредственно получить реализацию класса, без необходимости внедрять детали реализации класса
xxxService service1 = DiPlugin.useInstance("xxxService", "test", xxxService.class);
service1.say("Hello, tuz!");
// Вы можете подумать, что в предыдущем методе слишком много параметров
// Да, вы правы, это именно так. xxxService и xxxService.class
// Когда ключ и имя класса совпадают, значение ключа на самом деле можно опустить
// Обратите внимание, что ключ xxxService в файле конфигурации - это xxxService
xxxService service2 = DiPlugin.useInstance(xxxService.class);
service2.say("Hello, tuz!");
// Точно так же вы можете не указывать пространство имен, но это приведет к повторному поиску!
//tuz.load(new ClasspathPropertiesLoader("test.properties"));
//xxxService service3 = DiPlugin.useInstance("xxxService", xxxService.class);
//service3.say("Hello, Tuz!");
}
}
public class TuzSimpleDemo3 {
public static void main(String[] args) throws Throwable {
// Загрузить этот файл JSON
// После загрузки вы можете свободно использовать его в глобальном масштабе
Tuz tuz = Tuz.instance();
tuz.load(new ClasspathJSONLoader("test.json"));
// Рекомендуется дать этому файлу пространство имён, если оно не указано вручную, Tuz будет использовать имя файла в качестве пространства имён
// Tuz.load(new ClasspathJSONLoader("test.json", "test"));
// Конечно, помимо загрузки ресурсов из пути к классам, вы также можете загружать ресурсы из файловой системы
//Tuz.load(new FileSystemJSONLoader("E:\\JavaProject\\Tuz\\src\\test\\resources\\test.json"));
// Поскольку по умолчанию используется кодировка символов UTF8, если ваш файл не в формате UTF8, могут возникнуть проблемы с искажением символов
// В этом случае вам нужно самостоятельно указать кодировку символов этого файла
//Tuz.load(новый ClasspathJSONLoader ("test.json", StandardCharsets.ISO_8859_1));
/*
{
"status": 0,
"message": "success",
"ok": true,
"data": {
"title": {
"id": "001",
"name": "test",
"null": {}
},
"content": [
{
"id": "001",
"value": "hello 001",
"arr": [1, "非你莫属尽快发你说的", true]
},
{
"id": "002",
"value": "hello 002"
}
]
}
}
*/
// Если вам нужно сослаться на значение в этом JSON, просто обратитесь к нему следующим образом
// Разве это не удобно? Ха-ха-ха ^_^
System.out.println(tuz.use("status")); // ===> 0
System.out.println(tuz.use("message")); // ===> success
System.out.println(tuz.use("ok")); // ===> true
System.out.println(tuz.use("data")); // ===> {"title":{"null":{},"name":"test","id":"001"},"content":[{"arr":[1,"非你莫属尽快发你说的",true],"id":"001","value":"hello 001"},{"id":"002","value":"hello 002"}]}
System.out.println(tuz.use("data.title")); // ===> {"null":{},"name":"test","id":"001"}
System.out.println(tuz.use("data.title.id")); // ===> 001
System.out.println(tuz.use("data.title.name")); // ===> test
System.out.println(tuz.use("data.title.null")); // ===> {}
System.out.println(tuz.use("data.content")); // ===> [{"arr":[1,"bfdjhsb",true],"id":"001","value":"hello 001"},{"id":"002","value":"hello 002"}]
System.out.println(tuz.use("data.content[0].id")); // ===> 001
System.out.println(tuz.use("data.content[0].value")); // ===> hello 001
System.out.println(tuz.use("data.content[0].arr")); // ===> [1,"bfdjhsb",true]
System.out.println(tuz.use("data.content[0].arr[0]")); // ===> 1
*Примечание: данный текст является переводом исходного текста, предоставленного в запросе.* ```
Систем.аут.принталН(туз.юзэ("дата.контент[0].арр[1]")); // ===> бфджхсб
Систем.аут.принталН(туз.юзэ("дата.контент[0].арр[2]")); // ===> тру
Систем.аут.принталН(туз.юзэ("дата.контент[1].ид")); // ===> 002
Систем.аут.принталН(туз.юзэ("дата.контент[1].вэлью")); // ===> хелоу 002
// Конечно, если у вас есть несколько JSON-файлов с одинаковыми ключами, вам нужно добавить пространство имён
// Здесь «тест» — это пространство имён, которое нужно указать при вызове tuz.load
туз.лоад(нью класспазхап джсонлоадер("тест.джсон", "тест"));
систем.аут.принталН(туз.юзэ("статус", "тест")); // ===> 0
// Конечно, если вы используете в программе строку JSON, вы также можете использовать AbstractJSONLoader для загрузки и использования
финал стринг джсонстринг = "{\"титул\":{\"нулл\":{},\"нэйм\":\"тест\",\"ид\":\"001\"},\"контент\":[{\"арр\":[1,\"фэн дзи мосу цзин куай фа чжи дэ\", тру],\"ид\":\"001\",\"вэлью\":\"хелоу 001\"},{\"ид\":\"002\",\"вэлью\":\"хелоу 002\"}]}";
туз.лоад(ньют абстракстджсонлоадер(джсонстринг) {
@оверрид
публик стринг нэймспейс() {
ретюрн "програм";
}
});
систем.аут.принталН(туз.юзэ("контент[0].арр")); // ===> [1,"фэн дзи мосу цзин куай фа чжи дэ",тру]
}
// Конфигурация пользовательских настроек
публик класс тузконфигдемо {
публик статик воид мэйн(стрэнг арс) трис тирэз {
// Мы сначала используем cn.com.fishin.tuz.demo.TuzSimpleDemo2 как точку входа
// Сначала посмотрим на оригинальный пример:
туз туз = туз.инстанс();
туз.лоад(нью класспазхап пропертислоадер("тест.пропертис"));
хххсервис сервис = диплэг.юз инстанс(хххсервис.класс);
сервис.сэй("Хелоу, Туз!");
// По умолчанию созданные объекты являются одноэлементными
// См. cn.com.fishin.tuz.core.TuzConfig
хххсервис сервис1 = диплэг.юз инстанс(хххсервис.класс);
хххсервис сервис2 = диплэг.юз инстанс(хххсервис.класс);
систем.аут.принталН(сервис1 == сервис2); // возвращает ===> тру
// Поскольку у Tuz есть один набор по умолчанию, который содержит атрибут
// Получение экземпляра класса по умолчанию является истинным, то есть одноэлементным
// приватная булеан синглтон = тру;
// Вы можете напрямую установить значение по умолчанию в Tuz, но это не рекомендуется
туз.гет конфиг().сет синглтон(фолс);
// Таким образом, полученный объект является многоэкземплярным
хххсервис сервис3 = диплэг.юз инстанс(хххсервис.класс);
хххсервис сервис4 = диплэг.юз инстанс(хххсервис.класс);
систем.аут.принталН(сервис3 == сервис4); // возвращает ===> фолс
// Вышеупомянутое говорит, что вы можете напрямую устанавливать значения по умолчанию в Tuz, но не рекомендуется
// Правильный способ — создать новый объект конфигурации
тузконфиг нью конфиг = нью тузконфиг();
нью конфиг.сет синглтон(тру);
// Устанавливаем конфигурацию
туз.сэт конфиг(нью конфиг);
// Теперь полученный объект снова является одноэлементным!
хххсервис сервис5 = диплэг.юз инстанс(хххсервис.класс);
хххсервис сервис6 = диплэг.юз инстанс(хххсервис.класс);
систем.аут.принталН(сервис5 == сервис6); // возвращает ===> тру
}
}
//@Спрингбут аппликейшн
публик класс туз спринг бут демо {
/*
* Этот класс просто демонстрирует использование SpringBoot, и это не единственный способ его использования
*
* Когда-то при использовании Spring конфигурация файла могла изменять реализацию класса без изменения кода,
* Позже был выпущен SpringBoot, который действительно упростил множество операций с конфигурацией файлов,
* Кроме того, для микросервисов изменение реализации класса часто означает изменение сервиса, поэтому, когда возникает необходимость изменить требования и изменить код,
* Мы обычно можем понять и принять это, и даже если мы хотим прочитать конфигурацию из файла .properties, чтобы достичь цели не изменять код и изменять реализацию класса, это несложно, в конце концов, Spring уже очень прост в чтении файлов конфигурации,
* Однако эти бизнес-процессы на самом деле повторяются и имеют смысл, и именно здесь Tuz проявляет себя в хорошем повторном использовании и бизнес-ценности.
*/
// Вы можете выбрать использование статического блока для инициализации Tuz
// Конечно, вы также можете выбрать инициализацию в методе main
статик {
три точка туз туз = туз.инстанс();
туз.лоад(нью класспазхап пропертислоадер("тест.пропертис", "тест"));
}
публик статик воид мэин(стрэнг арс) {
// Помимо инициализации в статическом блоке, вы также можете инициализировать здесь или даже сочетать параметры args
// Делайте выбор в пользу разных сред для инициализации Туза
Туз.лоад(нью класспазхап пропертислоадер("тест.пропертис", "тест"));
// Это использование SpringBoot здесь не обсуждается
спринг аппликейшн.ран(туз спринг бут демо.класс, арс);
}
// Инициализация Spring Bean
//@Бин
публик хххсервис гэт ххх сервис() {
// Просто верните хххСервис
// Таким образом, вам нужно только изменить реализацию этого класса в test.properties,
// Не нужно менять код, не нужно писать лишний код
ретурн диплэг.юз инстанс(ххх сервис.класс);
}
}
``` **Использование перехватчиков для достижения развязки основного и вспомогательного бизнеса**
```java
public class ProxySimpleDemo {
/*
// В test пакете есть пример использования метода ProxyFactory.wrap
// Однако не рекомендуется использовать этот метод напрямую, так как этот метод больше похож на фабричный метод, предназначенный для внутреннего использования
SimpleClass simpleClass = new SimpleClass();
SimpleClass simpleClass1 = (SimpleClass) ProxyFactory.wrap(simpleClass,
new InterceptorInvocationHandler(simpleClass, new Interceptor[]{
new TestInterceptor(),
new TestInterceptor(),
new TestInterceptor()
}));
simpleClass1.test();
*/
public static void main(String[] args) throws Throwable {
// Аналогично, сначала загрузите файл ресурсов, чтобы получить конкретный класс реализации
Tuz tuz = Tuz.instance();
tuz.load(new ClasspathPropertiesLoader("test.properties", "test"));
// Непосредственно получите класс реализации, вместо того чтобы внедрять детали класса реализации
xxxService service = DiPlugin.useInstance(xxxService.class);
// Выше показано простейшее использование метода внедрения зависимостей
// Но теперь вы пришли с новым требованием, вам нужно добавить два требования к существующей системе:
// 1. Теперь система добавила redis в качестве системы кэширования, перед вызовом метода сначала найдите в системе кэширования
// Поиск не удался, затем поиск из базы данных и загрузка данных в систему кэширования
// 2. Необходимо добавить функцию регистрации журнала ко всем бизнес-методам
// Эти две точки являются второстепенными бизнес-функциями, и не рекомендуется напрямую записывать их в существующий бизнес или если вы не можете изменить существующий код
// Вам необходимо использовать идеи аспектно-ориентированного программирования для обновления вашего бизнес-класса
// Tuz использует перехватчики для достижения этой цели
// Интерфейс верхнего уровня перехватчика: cn.com.fishin.tuz.interceptor.Interceptor
// Однако не рекомендуется напрямую использовать этот перехватчик, рекомендуется использовать cn.com.fishin.tuz.interceptor.DefaultInterceptor
// Затем выборочно перепишите определенные методы для достижения определенных бизнес-функций
// Не рекомендуется напрямую использовать эту фабрику классов, рекомендуется использовать метод cn.com.fishin.tuz.plugin.ProxyPlugin для получения объекта прокси после
/*
xxxService xxxService = ProxyPlugin.useInstance(xxxService.class,
new Interceptor[]{
new CacheInterceptor(),
new LogInterceptor()
});
*/
// Обратите внимание: когда этот класс может быть унаследован, используйте CGlib для реализации динамического прокси
// Если его нельзя унаследовать, используйте JDK для динамического прокси, в это время требуется, чтобы этот класс реализовал интерфейс, и используйте интерфейс для приема
xxxService serviceProxy = ProxyPlugin.useInstance(xxxService.class, new Interceptor[]{
new CacheInterceptor(), // Перехватчик кэша
new LogInterceptor(), // Перехватчик журнала
});
// Это сравнение
System.out.println("====================== Использование перехватчика перед бизнесом ===================");
service.say("Не использовал перехватчик...");
System.out.println("====================== Использование перехватчика перед бизнесом ===================");
System.out.println("====================== Использование перехватчика после бизнеса ===================");
serviceProxy.say("Использовать перехватчик...");
System.out.println("====================== Использование перехватчика после бизнеса ===================");
// Это второе сравнение
System.out.println("====================== Использование перехватчика перед бизнесом ===================");
service.hung(18, 16);
System.out.println("====================== Использование перехватчика перед бизнесом ===================");
System.out.println("====================== Использование перехватчика после бизнеса ===================");
serviceProxy.hung(81, 61);
System.out.println("====================== Использование перехватчика после бизнеса ===================");
/*
// Результат выполнения:
====================== Использование перехватчика перед бизнесом ===================
Не использовал перехватчик...
====================== Использование перехватчика перед бизнесом ===================
====================== Использование перехватчика после бизнеса ===================
Запись журнала в норме операция => public void cn.com.fishin.tuz.demo.xxxServiceImpl.say(java.lang.String)
Поиск данных в кэше: [Ljava.lang.Object;@29774679
Данные не найдены в кэше!
Использовать перехватчик...
Загрузка данных null в кэш...
====================== Использование перехватчика после бизнеса ===================
====================== Использование перехватчика перед бизнесом ===================
18 hung 16
====================== Использование перехватчика перед бизнесом ===================
====================== Использование перехватчика после бизнеса ===================
Запись журнала в норме операция => public void cn.com.fishin.tuz.demo.xxxServiceImpl.hung(int,int)
Поиск данных в кэше: [Ljava.lang.Object;@26653222
Данные найдены в кэше!
====================== Использование перехватчика после бизнеса ===================
*/
// Следует отметить, что, поскольку используется CGlib, класс, который будет проксироваться, не может быть окончательным
// То есть он должен быть наследуемым, потому что CGlib использует ASM для создания подклассов и полиморфизма для достижения эффекта динамического прокси
// Кроме того, является ли экземпляр, созданный динамическим прокси, одноэлементным или нет, зависит от конфигурации Tuz
// Для получения подробной информации см. cn.com.fishin.tuz.core.TuzConfig.isSingleton
// По умолчанию используется режим одиночного экземпляра, то есть независимо от того, сколько прокси-объектов создано, они все одинаковы
// Если вам нужен многоэкземплярный режим, вы можете изменить конфигурацию Tuz и вызвать
}
``` **7. Redis 资源加载器**
```java
public class TuzSimpleDemo4 {
public static void main(String[] args) throws Throwable {
// Использование RedisLoader для загрузки ресурсов на Redis
final String namespace = "192.168.32.131:6379";
Tuz tuz = Tuz.instance();
Loader redisLoader = new RedisLoader(namespace,
new JedisRedisConnection(new Jedis("192.168.32.131", 6379)));
tuz.load(redisLoader);
// Теперь можно использовать ресурсы на Redis как обычные ресурсы
tuz.appendResource(redisLoader, "key", "哈哈哈");
System.out.println("key ===> " + tuz.use("key"));
System.out.println("key1 ===> " + tuz.use("key1"));
System.out.println("key2 ===> " + tuz.use("key2"));
tuz.unLoad(redisLoader);
System.out.println("key ===> " + tuz.use("key"));
}
private static Map<String, String> manyEntries() {
Map<String, String> entries = new HashMap<>(8);
for (int i = 0; i < 4; i++) {
entries.put("key" + i, "value" + i);
}
return entries;
}
}
8. Больше использования в разработке
Вы можете легко настроить свои собственные плагины.
Например, вы можете создать свой собственный загрузчик, просто реализовав интерфейс cn.com.fishin.tuz.core.Loader
.
Для получения дополнительной информации о демонстрационных примерах использования, пожалуйста, обратитесь к модулю test в cn.com.fishin.tuz.demo. Документ и несколько примеров кода, также была скорректирована структура пакета.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )