{"id":15196868,"url":"https://github.com/pf4j/pf4j-spring","last_synced_at":"2025-05-14T16:15:33.779Z","repository":{"id":17919168,"uuid":"20886134","full_name":"pf4j/pf4j-spring","owner":"pf4j","description":"Plugin Framework for Spring (PF4J - Spring Framework integration)","archived":false,"fork":false,"pushed_at":"2025-01-21T07:20:52.000Z","size":137,"stargazers_count":364,"open_issues_count":34,"forks_count":113,"subscribers_count":22,"default_branch":"master","last_synced_at":"2025-04-06T22:01:32.699Z","etag":null,"topics":["java","modularity","pf4j","plugins","spring-framework"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pf4j.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-06-16T13:38:58.000Z","updated_at":"2025-04-03T10:05:56.000Z","dependencies_parsed_at":"2024-06-21T12:53:45.671Z","dependency_job_id":"b00a9878-046b-432a-9c09-869db7824d90","html_url":"https://github.com/pf4j/pf4j-spring","commit_stats":null,"previous_names":["decebals/pf4j-spring"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pf4j%2Fpf4j-spring","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pf4j%2Fpf4j-spring/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pf4j%2Fpf4j-spring/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pf4j%2Fpf4j-spring/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pf4j","download_url":"https://codeload.github.com/pf4j/pf4j-spring/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248804773,"owners_count":21164131,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["java","modularity","pf4j","plugins","spring-framework"],"created_at":"2024-09-28T00:05:11.706Z","updated_at":"2025-04-14T00:51:37.726Z","avatar_url":"https://github.com/pf4j.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"PF4J - Spring Framework integration\n=====================\n[![Join the chat at https://gitter.im/decebals/pf4j](https://badges.gitter.im/decebals/pf4j.svg)](https://gitter.im/decebals/pf4j?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n[![GitHub Actions Status](https://github.com/pf4j/pf4j-spring/actions/workflows/build.yml/badge.svg)](https://github.com/pf4j/pf4j-spring/actions/workflows/build.yml)\n[![Maven Central](http://img.shields.io/maven-central/v/org.pf4j/pf4j-spring.svg)](http://search.maven.org/#search|ga|1|pf4j-spring)\n\nThis project is a proof of concept related to how you can integrate [PF4J](https://github.com/pf4j/pf4j) with Spring Framework.\n\nComponents\n-------------------\n- **ExtensionsInjector** allows PF4J's extensions to be exposed as Spring beans.\n- **SpringPlugin** your plugin extends this class if your plugin contains Spring beans\n- **SpringExtensionFactory** use this ExtensionFactory in your PluginManager if you have SpringPlugins\n- **SpringPluginManager** a Spring aware PluginManager\n\nUsing Maven\n-------------------\nIn your pom.xml you must define the dependencies to PF4J-Spring artifact with:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.pf4j\u003c/groupId\u003e\n    \u003cartifactId\u003epf4j-spring\u003c/artifactId\u003e\n    \u003cversion\u003e${pf4j-spring.version}\u003c/version\u003e\n\u003c/dependency\u003e    \n```\n\nwhere ${pf4j-spring.version} is the last pf4j-spring version.\n\nYou may want to check for the latest released version using [Maven Search](http://search.maven.org/#search%7Cga%7C1%7Cpf4j-spring)\n\nAlso you can use the latest SNAPSHOT via the Sonatype Maven Repository. For this, you must add above lines in your `pom.xml`:\n\n```xml\n\u003crepositories\u003e\n    \u003crepository\u003e\n        \u003cid\u003esonatype-nexus-snapshots\u003c/id\u003e\n        \u003curl\u003ehttps://oss.sonatype.org/content/repositories/snapshots\u003c/url\u003e\n        \u003creleases\u003e\n            \u003cenabled\u003efalse\u003c/enabled\u003e\n        \u003c/releases\u003e\n        \u003csnapshots\u003e\n            \u003cenabled\u003etrue\u003c/enabled\u003e\n        \u003c/snapshots\u003e\n    \u003c/repository\u003e\n\u003c/repositories\u003e\n```\n\nHow to use\n-------------------\nCreate the Spring configuration (declare some beans) using annotations with:\n```java\n@Configuration\npublic class SpringConfiguration {\n\n    @Bean\n    public SpringPluginManager pluginManager() {\n        return new SpringPluginManager();\n    }\n\n    @Bean\n    @DependsOn(\"pluginManager\")\n    public Greetings greetings() {\n        return new Greetings();\n    }\n\n}\n```\n\n`SpringExtensionFactory` creates a new extension instance every time a request is done.  \nIf you want a singleton extension instance please use `SingletonSpringExtensionFactory` that always returns a specific instance. Optional you can specify the extension classes for which you want singletons.  \n\nStart your application (plain java code):\n```java\npublic class Boot {\n\n    public static void main(String[] args) {\n        // retrieves the Spring application context\n        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);\n\n        // retrieves automatically the extensions for the Greeting.class extension point\n        Greetings greetings = applicationContext.getBean(Greetings.class);\n        greetings.printGreetings();\n\n        // stop plugins\n        PluginManager pluginManager = applicationContext.getBean(PluginManager.class);\n        /*\n        // retrieves manually the extensions for the Greeting.class extension point\n        List\u003cGreeting\u003e greetings = pluginManager.getExtensions(Greeting.class);\n        System.out.println(\"greetings.size() = \" + greetings.size());\n        */\n        pluginManager.stopPlugins();\n    }\n\n}\n```\n\nConsume the PF4J extensions as Spring beans:\n```java\npublic class Greetings {\n\n    @Autowired\n    private List\u003cGreeting\u003e greetings;\n\n    public void printGreetings() {\n        System.out.println(String.format(\"Found %d extensions for extension point '%s'\", greetings.size(), Greeting.class.getName()));\n        for (Greeting greeting : greetings) {\n            System.out.println(\"\u003e\u003e\u003e \" + greeting.getGreeting());\n        }\n    }\n\n}\n```\n\nThe output is:\n```\nFound 2 extensions for extension point 'org.pf4j.demo.api.Greeting'\n\u003e\u003e\u003e Welcome\n\u003e\u003e\u003e Hello\n```\n\nBellow I present you a more complex example where a plugin (see demo plugin2 - HelloPlugin) uses Spring Framework internally.\n\nFirst, create an interface `MessageProvider` with an implementation class `HelloMessageProvider`\n```java\npublic interface MessageProvider {\n\n    String getMessage();\n\n}\n\npublic class HelloMessageProvider implements MessageProvider {\n\n    @Override\n    public String getMessage() {\n        return \"Hello\";\n    }\n\n}\n```\n\nDeclare the plugin's beans via Spring Configuration\n```java\n@Configuration\npublic class SpringConfiguration {\n\n    @Bean\n    public MessageProvider messageProvider() {\n        return new HelloMessageProvider();\n    }\n\n}\n```\n\nCreate my (Spring) plugin\n```java\npublic class HelloPlugin extends SpringPlugin {\n\n    public HelloPlugin(PluginWrapper wrapper) {\n        super(wrapper);\n    }\n\n    @Override\n    public void start() {\n        System.out.println(\"HelloPlugin.start()\");\n    }\n\n    @Override\n    public void stop() {\n        System.out.println(\"HelloPlugin.stop()\");\n        super.stop(); // to close applicationContext\n    }\n\n    @Override\n    protected ApplicationContext createApplicationContext() {\n        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();\n        applicationContext.setClassLoader(getWrapper().getPluginClassLoader());\n        applicationContext.register(SpringConfiguration.class);\n        applicationContext.refresh();\n\n        return applicationContext;\n    }\n\n    @Extension\n    public static class HelloGreeting implements Greeting {\n\n        @Autowired\n        private MessageProvider messageProvider;\n\n        @Override\n        public String getGreeting() {\n//            return \"Hello\";\n            // complicate a little bit the code\n           return messageProvider.getMessage();\n        }\n\n    }\n\n}\n```\n\nReady, your extension is available in your application via `PluginManager` or `Spring Autowire`.\n\nFor more details please see the demo application.\n\nImplementation details\n-------------------\n__ExtensionsInjector__ injects each PF4J's extension as a bean in Spring Framework. For example if you run the demo application\nyou will see these lines in log:\n\n```\n2014-06-16 16:40:36,573 DEBUG org.pf4j.spring.ExtensionsInjector - Registering extensions of the plugin 'welcome-plugin' as beans\n2014-06-16 16:40:36,586 DEBUG org.pf4j.spring.ExtensionsInjector - Register extension 'org.pf4j.demo.welcome.WelcomePlugin$WelcomeGreeting' as bean\n2014-06-16 16:40:36,589 DEBUG org.pf4j.spring.ExtensionsInjector - Registering extensions of the plugin 'hello-plugin' as beans\n2014-06-16 16:40:36,589 DEBUG org.pf4j.spring.ExtensionsInjector - Register extension 'org.pf4j.demo.hello.HelloPlugin$HelloGreeting' as bean\n```\n\nThe bean name is the extension class name (for example 'org.pf4j.demo.welcome.WelcomePlugin$WelcomeGreeting').\n\nFor more information please see the demo sources.\n\nDemo\n-------------------\nI have a tiny demo application. The demo application is in demo package.\n\nRun the pf4j-spring demo (Boot class contains the main method) from IDE (IntelliJ in my case) with these arguments as VM options:\n```\n-Dpf4j.mode=development\n```\n\nand working directory:\n```\npf4j-spring/demo/app\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpf4j%2Fpf4j-spring","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpf4j%2Fpf4j-spring","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpf4j%2Fpf4j-spring/lists"}