When specifying an implementation of a plugin module, you can specify the class name that the plugin framework should resolve, instantiate, and inject for you. Instances are created per usage (prototype-scope) and Spring injection will happen via autodetection autowire mode, which tries constructor injection, falling back to setter injection by type.
In Atlassian Plugin Framework 2.5 and later, the instantiation of a plugin module has been improved to give you full control how your module classes will be created via a new optional prefix-based, pluggable PrefixModuleFactory interface. Out of the box, the framework ships with support for the "bean:"
prefix that allows you to refer to a Spring bean by ID instead of specifying a classname in the module descriptor. This gives you complete control over the creation, scope, and injection of your plugin modules.
Everything from here down is available in | Atlassian Plugin Framework 2.5 and later. |
For example, if you wanted to instantiate a class, you could specify a servlet class via:
1 2<servlet key="myServlet" class="class:com.example.MyServlet" />
Since the "class" prefix is the default, you could also configure the Servlet via:
1 2<servlet key="myServlet" class="com.example.MyServlet" />
The following prefixes are supported:
Prefix | Description |
---|---|
class | Instantiates the class via Spring using the autodetect autowire mode Default: true |
bean | Looks up the specified bean ID in the Spring context |
Before you can use the "bean" prefix, you must create a bean that lives in the Spring context. This bean can be specified via the <component>
module type or in a custom Spring XML file living in META-INF/spring
. When using Spring XML directly, you have full control over the creation, scope, and injection of the bean. Reasons you may want to use the "bean" prefix include:
In atlassian-plugin.xml
:
1 2<component key="myServlet" class="com.example.MyServlet" /> <servlet key="myServlet" class="bean:myServlet" />
In META-INF/spring/myPlugin.xml
:
1 2<bean id="myServlet" class="com.example.MyServlet" autowire="byName"/>
In atlassian-plugin.xml
:
1 2<servlet key="myServlet" class="bean:myServlet" />
You can create your own prefix for further control over the creation of module instances. This technique can be used to do things like delegating the creation to a scripting engine or automatically wrapping all module instances in proxies.
Let's say we want to create a new prefix called "named", which instantiates all module instances via a single argument constructor that expects the name of the plugin.
Our NamedPrefixModuleFactory
loads the class then instantiates its constructor with the plugin key:
1 2public class NamedPrefixModuleFactory implements PrefixModuleFactory { public String getPrefix() { return "named"; } public <T> T createModule(String name, ModuleDescriptor<T> moduleDescriptor) throws PluginParseException { try { Class clazz = getClass().getClassLoader().loadClass(name); return (T) clazz.getConstructor(String.class).newInstance(moduleDescriptor.getPluginKey()); } catch (Exception e) { throw new RuntimeException("Obviously non-production code here...", e); } } }
Just by exposing the NamedPrefixModuleFactory
as a component, or more specifically, as a bean in our BeanFactory
, the plugin framework will pick it up and use it for plugin module prefix resolution:
1 2<component key="namedPrefix" class="com.example.NamedPrefixModuleFactory" />
The prefix is now able to be used by plugin modules that expect objects like the servlet module type:
1 2<servlet key="myServlet" class="named:com.example.MyServlet" />
Rate this page: