Rumah Java javaTutorial Menggunakan anotasi dalam Java untuk membuat strategi

Menggunakan anotasi dalam Java untuk membuat strategi

Jan 10, 2025 pm 12:13 PM

Usando annotations em Java para fazer um strategy

Saya melalui situasi yang sangat menarik di tempat kerja dan saya ingin berkongsi penyelesaiannya di sini.

Bayangkan anda perlu memproses satu set data. Dan untuk menangani set data ini, anda mempunyai beberapa strategi berbeza untuk ini. Contohnya, saya perlu mencipta strategi untuk cara mengambil koleksi data daripada S3, atau contoh dalam repositori setempat, atau diluluskan sebagai input.

Dan sesiapa yang akan menentukan strategi ini adalah orang yang membuat permintaan:

Saya ingin mendapatkan data dalam S3. Ambil data yang dijana pada hari X antara jam H1 dan H2, iaitu daripada klien Abóbora. Dapatkan 3000 data terakhir yang memenuhi ini.

Atau sebaliknya:

Ambil data contoh yang anda ada di sana, salin 10000 kali untuk melakukan ujian tekanan.

Atau pun:

Saya mempunyai direktori ini, anda juga mempunyai akses kepadanya. Dapatkan segala-galanya dalam direktori itu dan secara rekursif ke dalam subdirektori.

Dan juga akhirnya:

Ambil unit data ini yang terdapat dalam input dan gunakannya.

Bagaimana untuk melaksanakan?

Fikiran pertama saya ialah: "bagaimana saya boleh menentukan bentuk input saya dalam Java?"

Dan saya mencapai kesimpulan pertama, sangat penting untuk projek: "anda tahu apa? Saya tidak akan menentukan bentuk. Tambah Peta yang boleh mengendalikannya."

Selain itu, kerana saya tidak meletakkan sebarang bentuk dalam DTO, saya mempunyai kebebasan sepenuhnya untuk mencuba input.

Jadi selepas mewujudkan bukti konsep, kita sampai pada situasi: kita perlu keluar daripada tekanan POC dan beralih kepada sesuatu yang hampir dengan penggunaan sebenar.

Perkhidmatan yang saya lakukan adalah untuk mengesahkan peraturan. Pada asasnya, apabila menukar peraturan, saya perlu mengambil peraturan itu dan memadankannya dengan peristiwa yang berlaku dalam aplikasi pengeluaran. Atau, jika aplikasi telah ditukar dan tiada pepijat, jangkaan ialah keputusan untuk peraturan yang sama akan kekal sama untuk data yang sama; Sekarang, jika keputusan untuk peraturan yang sama menggunakan set data yang sama diubah... nah, itu potensi masalah.

Jadi, saya memerlukan aplikasi ini untuk menjalankan ujian belakang peraturan. Saya perlu menekan aplikasi sebenar yang menghantar data untuk penilaian dan peraturan yang dipersoalkan. Penggunaan ini agak pelbagai:

  • sahkan potensi penyelewengan apabila mengemas kini aplikasi
  • sahkan sama ada peraturan yang diubah mengekalkan tingkah laku yang sama
    • contohnya, mengoptimumkan masa pelaksanaan peraturan
  • semak sama ada perubahan dalam peraturan menjana perubahan yang dijangkakan dalam keputusan
  • sahkan bahawa perubahan dalam aplikasi sebenarnya menjadikannya lebih cekap
    • contohnya, menggunakan versi baharu GraalVM dengan JVMCI dihidupkan meningkatkan bilangan permintaan yang boleh saya buat?

Jadi, untuk itu, saya memerlukan beberapa strategi untuk asal usul peristiwa:

  • dapatkan data sebenar daripada S3
  • ambil data yang menjadi sampel dalam repositori dan salinnya beberapa kali
  • dapatkan data dari lokasi tertentu pada mesin tempatan saya

Dan saya juga memerlukan strategi yang berbeza daripada peraturan saya:

  • lulus melalui input
  • menggunakan rintisan yang berjalan pantas
  • menggunakan sampel berdasarkan peraturan pengeluaran
  • gunakan laluan ini di sini pada mesin saya

Bagaimana untuk menangani perkara ini? Baiklah, biarkan pengguna memberikan data!

API untuk Strategi

Adakah anda tahu sesuatu yang selalu menarik perhatian saya tentang json-schema? Ini di sini:

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://json-schema.org/draft/2020-12/schema",
    "$vocabulary": {
        //...
    }
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Medan ini bermula dengan $. Pada pendapat saya, mereka digunakan untuk menunjukkan metadata. Jadi mengapa tidak gunakan ini dalam input data untuk menunjukkan metadata strategi mana yang sedang digunakan?

{
    "dados": {
        "$strategy": "sample",
        "copias": 15000
    },
    //...
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Sebagai contoh, saya boleh memesan 15000 salinan data yang saya ada sebagai sampel. Atau minta beberapa perkara daripada S3, membuat pertanyaan dalam Athena:

{
    "dados": {
        "$strategy": "athena-query",
        "limit": 15000,
        "inicio": "2024-11-25",
        "fim": "2024-11-26",
        "cliente": "Abóbora"
    },
    //...
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Atau dalam laluan setempat?

{
    "dados": {
        "$strategy": "localpath",
        "cwd": "/home/jeffque/random-project-file",
        "dir": "../payloads/esses-daqui/top10-hard/"
    },
    //...
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Jadi saya boleh mewakilkan kepada pemilihan strategi di hadapan.

Semakan kod dan fasad

Pendekatan pertama saya untuk menangani strategi ialah:

public DataLoader getDataLoader(Map<String, Object> inputDados) {
    final var strategy = (String) inputDados.get("$strategy");
    return switch (strategy) {
        case "localpath" -> new LocalpathDataLoader();
        case "sample" -> new SampleDataLoader(resourcePatternResolver_spring);
        case "athena-query" -> new AthenaQueryDataLoader(athenaClient, s3Client);
        default -> new AthenaQueryDataLoader(athenaClient, s3Client);
    }
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Jadi arkitek saya bertanya dua soalan semasa semakan kod:

  • "mengapa anda membuat seketika segala-galanya dan tidak membiarkan Spring bekerja untuk anda?"
  • dia mencipta DataLoaderFacade dalam kod dan meninggalkannya separuh masak

Apa yang saya faham daripada ini? Menggunakan fasad adalah idea yang baik untuk menyerahkan pemprosesan ke sudut yang betul dan... untuk melepaskan kawalan manual?

Nah, banyak keajaiban berlaku kerana Musim Bunga. Memandangkan kami berada di rumah Java dengan kepakaran Java, mengapa tidak menggunakan Java/Spring idiomatik, bukan? Hanya kerana Saya sebagai individu mendapati beberapa perkara sukar difahami tidak semestinya ianya rumit. Jadi, mari kita menghayati dunia sihir suntikan pergantungan Java.

Mencipta objek fasad

Apa dulu:

final var dataLoader = getDataLoader(inputDados)
dataLoader.loadData(inputDados, workingPath);
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Menjadi:

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://json-schema.org/draft/2020-12/schema",
    "$vocabulary": {
        //...
    }
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Jadi lapisan pengawal saya tidak perlu mengurus ini. Biarkan ia pada fasad.

Jadi, bagaimana kita akan membuat fasad? Nah, untuk memulakan, saya perlu menyuntik semua objek ke dalamnya:

{
    "dados": {
        "$strategy": "sample",
        "copias": 15000
    },
    //...
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Ok, untuk DataLoader utama saya menulisnya sebagai @Primary sebagai tambahan kepada @Service. Selebihnya saya tulis sahaja dengan @Service.

Uji ini di sini, tetapkan getDataLoader untuk mengembalikan null hanya untuk mencuba cara Spring memanggil pembina dan... ia berfungsi. Sekarang saya perlu nota dengan metadata setiap perkhidmatan strategi yang mereka gunakan...

Bagaimana untuk melakukan ini...

Nah, lihat! Di Java kami mempunyai anotasi! Saya boleh mencipta anotasi masa jalan yang mempunyai di dalamnya strategi yang digunakan oleh komponen itu!

Jadi saya boleh mempunyai sesuatu seperti ini dalam AthenaQueryDataLoader:

{
    "dados": {
        "$strategy": "athena-query",
        "limit": 15000,
        "inicio": "2024-11-25",
        "fim": "2024-11-26",
        "cliente": "Abóbora"
    },
    //...
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Dan saya juga boleh mempunyai alias, mengapa tidak?

{
    "dados": {
        "$strategy": "localpath",
        "cwd": "/home/jeffque/random-project-file",
        "dir": "../payloads/esses-daqui/top10-hard/"
    },
    //...
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Dan tunjukkan!

Tetapi bagaimana untuk mencipta anotasi ini? Nah, saya memerlukannya untuk mempunyai atribut yang merupakan vektor rentetan (pengkompil Java sudah berurusan dengan menyediakan rentetan tunggal dan mengubahnya menjadi vektor dengan 1 kedudukan). Nilai lalai ialah nilai. Ia kelihatan seperti ini:

public DataLoader getDataLoader(Map<String, Object> inputDados) {
    final var strategy = (String) inputDados.get("$strategy");
    return switch (strategy) {
        case "localpath" -> new LocalpathDataLoader();
        case "sample" -> new SampleDataLoader(resourcePatternResolver_spring);
        case "athena-query" -> new AthenaQueryDataLoader(athenaClient, s3Client);
        default -> new AthenaQueryDataLoader(athenaClient, s3Client);
    }
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Jika medan anotasi bukan nilai, saya perlu menyatakannya dengan jelas dan itu akan kelihatan hodoh, seperti dalam anotasi EstrategiaFeia:

final var dataLoader = getDataLoader(inputDados)
dataLoader.loadData(inputDados, workingPath);
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Bunyinya tidak begitu natural pada pendapat saya.

Baiklah, memandangkan itu, kami masih memerlukan:

  • ekstrak anotasi kelas daripada objek yang diluluskan
  • buat peta rentetan anak panah kanan pemuat data (atau rentetan anak panah kanan T)

Mengekstrak anotasi dan memasang peta

Untuk mengekstrak anotasi, saya perlu mempunyai akses kepada kelas objek:

dataLoaderFacade.loadData(inputDados, workingPath);
Salin selepas log masuk
Salin selepas log masuk

Selain itu, bolehkah saya bertanya sama ada kelas ini diberi anotasi dengan anotasi seperti Strategi:

@Service // para o Spring gerenciar esse componente como um serviço
public class DataLoaderFacade implements DataLoader {

    public DataLoaderFacade(DataLoader primaryDataLoader,
                            List<DataLoader> dataLoaderWithStrategies) {
        // armazena de algum modo
    }

    @Override
    public CompletableFuture<Void> loadData(Map<String, Object> input, Path workingPath) {
        return getDataLoader(input).loadData(input, workingPath);
    }

    private DataLoader getDataLoader(Map<String, Object> input) {
        final var strategy = input.get("$strategy");
        // magia...
    }
}
Salin selepas log masuk
Salin selepas log masuk

Adakah anda ingat bahawa ia mempunyai medan nilai? Nah, medan ini mengembalikan vektor rentetan:

@Service
@Primary
@Estrategia("athena-query")
public class AthenaQueryDataLoader implements DataLoader {
    // ...
}
Salin selepas log masuk

Tunjukkan! Tetapi saya mempunyai cabaran, kerana sebelum ini saya mempunyai objek jenis T dan sekarang saya mahu memetakan objek yang sama ke dalam, baik, (T, String)[]. Dalam strim, operasi klasik yang melakukan ini ialah flatMap. Dan Java juga tidak membenarkan saya memulangkan tupel seperti itu entah dari mana, tetapi saya boleh mencipta rekod dengannya.

Ia akan kelihatan seperti ini:

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://json-schema.org/draft/2020-12/schema",
    "$vocabulary": {
        //...
    }
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Bagaimana jika terdapat objek yang tidak dianotasi dengan strategi? Adakah ia akan memberi NPE? Lebih baik tidak, mari kita menapisnya sebelum NPE:

{
    "dados": {
        "$strategy": "sample",
        "copias": 15000
    },
    //...
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Memandangkan itu, saya masih perlu menyusun peta. Dan, lihatlah: Java sudah menyediakan pengumpul untuk ini! Collector.toMap(keyMapper, valueMapper)

{
    "dados": {
        "$strategy": "athena-query",
        "limit": 15000,
        "inicio": "2024-11-25",
        "fim": "2024-11-26",
        "cliente": "Abóbora"
    },
    //...
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Setakat ini, ok. Tetapi flatMap sangat mengganggu saya. Terdapat API Java baharu yang dipanggil mapMulti, yang mempunyai potensi untuk membiak:

{
    "dados": {
        "$strategy": "localpath",
        "cwd": "/home/jeffque/random-project-file",
        "dir": "../payloads/esses-daqui/top10-hard/"
    },
    //...
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kecantikan. Saya mendapatkannya untuk DataLoader, tetapi saya juga perlu melakukan perkara yang sama untuk RuleLoader. Atau mungkin tidak? Jika anda perasan, tiada apa-apa dalam kod ini yang khusus untuk DataLoader. Kita boleh abstrak kod ini!!

public DataLoader getDataLoader(Map<String, Object> inputDados) {
    final var strategy = (String) inputDados.get("$strategy");
    return switch (strategy) {
        case "localpath" -> new LocalpathDataLoader();
        case "sample" -> new SampleDataLoader(resourcePatternResolver_spring);
        case "athena-query" -> new AthenaQueryDataLoader(athenaClient, s3Client);
        default -> new AthenaQueryDataLoader(athenaClient, s3Client);
    }
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Di bawah fasad

Atas sebab utilitarian semata-mata, saya meletakkan algoritma ini dalam anotasi:

final var dataLoader = getDataLoader(inputDados)
dataLoader.loadData(inputDados, workingPath);
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Dan untuk fasad? Nah, kerja yang baik untuk mengatakan perkara yang sama. Saya memutuskan untuk mengabstrak ini:

dataLoaderFacade.loadData(inputDados, workingPath);
Salin selepas log masuk
Salin selepas log masuk

Dan fasad kelihatan seperti ini:

@Service // para o Spring gerenciar esse componente como um serviço
public class DataLoaderFacade implements DataLoader {

    public DataLoaderFacade(DataLoader primaryDataLoader,
                            List<DataLoader> dataLoaderWithStrategies) {
        // armazena de algum modo
    }

    @Override
    public CompletableFuture<Void> loadData(Map<String, Object> input, Path workingPath) {
        return getDataLoader(input).loadData(input, workingPath);
    }

    private DataLoader getDataLoader(Map<String, Object> input) {
        final var strategy = input.get("$strategy");
        // magia...
    }
}
Salin selepas log masuk
Salin selepas log masuk

Atas ialah kandungan terperinci Menggunakan anotasi dalam Java untuk membuat strategi. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Adakah perisian keselamatan syarikat menyebabkan aplikasi gagal dijalankan? Bagaimana cara menyelesaikan masalah dan menyelesaikannya? Adakah perisian keselamatan syarikat menyebabkan aplikasi gagal dijalankan? Bagaimana cara menyelesaikan masalah dan menyelesaikannya? Apr 19, 2025 pm 04:51 PM

Penyelesaian masalah dan penyelesaian kepada perisian keselamatan syarikat yang menyebabkan beberapa aplikasi tidak berfungsi dengan baik. Banyak syarikat akan menggunakan perisian keselamatan untuk memastikan keselamatan rangkaian dalaman. …

Bagaimanakah saya menukar nama kepada nombor untuk melaksanakan penyortiran dan mengekalkan konsistensi dalam kumpulan? Bagaimanakah saya menukar nama kepada nombor untuk melaksanakan penyortiran dan mengekalkan konsistensi dalam kumpulan? Apr 19, 2025 pm 11:30 PM

Penyelesaian untuk menukar nama kepada nombor untuk melaksanakan penyortiran dalam banyak senario aplikasi, pengguna mungkin perlu menyusun kumpulan, terutama dalam satu ...

Bagaimana untuk memudahkan isu pemetaan medan dalam dok sistem menggunakan mapstruct? Bagaimana untuk memudahkan isu pemetaan medan dalam dok sistem menggunakan mapstruct? Apr 19, 2025 pm 06:21 PM

Pemprosesan pemetaan medan dalam dok sistem sering menemui masalah yang sukar ketika melaksanakan sistem dok: bagaimana untuk memetakan medan antara muka sistem dengan berkesan ...

Bagaimana dengan elegan mendapatkan nama pemboleh ubah kelas entiti untuk membina keadaan pertanyaan pangkalan data? Bagaimana dengan elegan mendapatkan nama pemboleh ubah kelas entiti untuk membina keadaan pertanyaan pangkalan data? Apr 19, 2025 pm 11:42 PM

Apabila menggunakan Mybatis-Plus atau Rangka Kerja ORM yang lain untuk operasi pangkalan data, sering diperlukan untuk membina syarat pertanyaan berdasarkan nama atribut kelas entiti. Sekiranya anda secara manual setiap kali ...

Bagaimanakah Idea IntelliJ mengenal pasti nombor port projek boot musim bunga tanpa mengeluarkan log? Bagaimanakah Idea IntelliJ mengenal pasti nombor port projek boot musim bunga tanpa mengeluarkan log? Apr 19, 2025 pm 11:45 PM

Mula musim bunga menggunakan versi IntelliJideaultimate ...

Bagaimana cara menukar objek Java dengan selamat ke array? Bagaimana cara menukar objek Java dengan selamat ke array? Apr 19, 2025 pm 11:33 PM

Penukaran objek dan tatasusunan Java: Perbincangan mendalam tentang risiko dan kaedah penukaran jenis cast yang betul Banyak pemula Java akan menemui penukaran objek ke dalam array ...

Platform e-dagang SKU dan Reka Bentuk Pangkalan Data SPU: Bagaimana untuk mengambil kira kedua-dua atribut yang ditakrifkan oleh pengguna dan produk yang tidak berkesudahan? Platform e-dagang SKU dan Reka Bentuk Pangkalan Data SPU: Bagaimana untuk mengambil kira kedua-dua atribut yang ditakrifkan oleh pengguna dan produk yang tidak berkesudahan? Apr 19, 2025 pm 11:27 PM

Penjelasan terperinci mengenai reka bentuk jadual SKU dan SPU di platform e-dagang Artikel ini akan membincangkan isu reka bentuk pangkalan data SKU dan SPU dalam platform e-dagang, terutamanya bagaimana menangani jualan yang ditentukan pengguna ...

Bagaimana menggunakan penyelesaian cache Redis untuk merealisasikan keperluan senarai kedudukan produk dengan cekap? Bagaimana menggunakan penyelesaian cache Redis untuk merealisasikan keperluan senarai kedudukan produk dengan cekap? Apr 19, 2025 pm 11:36 PM

Bagaimanakah penyelesaian caching Redis menyedari keperluan senarai kedudukan produk? Semasa proses pembangunan, kita sering perlu menangani keperluan kedudukan, seperti memaparkan ...

See all articles