i have fxml controller has spring bean dependencies. can't find way autowire them in time before controller loaded, since i'm using custom fxml loader:
@bean @scope(proxymode = scopedproxymode.target_class, value = "prototype") public userprofile attachdoccontroller() throws ioexception { return (userprofile) loadcontroller("/myproject/forms/userprofile.fxml"); } fxmlloader loader = null; protected object loadcontroller(string url) throws ioexception { loader = new fxmlloader(getclass().getresource(url)); loader.load(); return loader.getcontroller(); } using approach, can autowire beans directly injecting them via @autowired annotation:
public class userprofile { @autowired mydependency mydependency; this leaves me dependent on spring, , leave me code maintainability issues later on. how can autowire dependencies spring xml file configuration fxml controller class? like:
<bean id="userprofile" class="myproject.controllerinjection.userprofile" scope="prototype"> <aop:scoped-proxy proxy-target-class="true"/> <property name="mydependency" ref="mydependency" /> </bean> <bean id="mydependency" class="myproject.controllerinjection.mydependency" scope="prototype"> <aop:scoped-proxy proxy-target-class="true"/> </bean> this seems better route, long-term project maintainability in mind, project gets larger.
update:
i'me not used lambda expressions. i've researched bit, integrating suggestion @james_d follows:
protected object loadbeancontroller(string url) throws ioexception { loader = new fxmlloader(getclass().getresource(url)); applicationcontext ctx = wakiliproject.getctx(); if (ctx != null) { system.out.println("load bean..............."); loader.setcontrollerfactory(ctx::getbean); } else { system.out.println("no app.ctx..............."); } return loader.getcontroller(); } gives null pointer whenever try calling method of mydependency. mydependency mydependency never gets injected userprofile.
when call fxmlloader.load(), loads fxml file. if there fx:controller attribute in root element, creates controller based on class specified (and injects fx:id-attributed elements controller instance, etc.). loader returns root of fxml file. controller intrinsically linked fxml root.
by default, fxmlloader maps controller class instance reflection, calling controllerclass.newinstance() (which invokes no-arg constructor of controller class). can configure this, overriding default behavior, specifying controllerfactory on fxmlloader.
the controllerfactory function maps class<?> object (constructed class name specified in fx:controller attribute) controller instance. if using spring manage controller instances, need function ask spring application context (bean factory) generate controller instance you. can fxmlloader.setcontrollerfactory(applicationcontext::getbean);. setup, loading fxml file via fxmlloader cause fxmlloader request controller class application context. application context can configured in of ways spring allows.
so config can like
@configuration public class config { @bean @scope(proxymode = scopedproxymode.target_class, value = "prototype") public userprofile attachdoccontroller() throws ioexception { return new userprofile(); } } of course, can inject dependencies in config class:
@bean @scope(proxymode = scopedproxymode.target_class, value = "prototype") public userprofile attachdoccontroller(mydependency mydependency) throws ioexception { return new userprofile(mydependency); } @bean public mydependency createdependency() { return new mydependencyimpl(); } then in ui work can do
fxmlloader loader = new fxmlloader(getclass().getresource("/myproject/forms/userprofile.fxml")); loader.setcontrollerfactory(applicationcontext::getbean); parent root = loader.load(); // since can initialized in controller d.i., // shouldn't need access it, if reason can userprofile controller = loader.getcontroller(); where applicationcontext spring application context. works whether application context use xml configuration, annotation-based configuration, or java configuration.
update
if, reason, cannot use java 8 or later, call setcontrollerfactory java 7 compatible looks like:
loader.setcontrollerfactory(new callback<class<?>, object>() { @override public object call(class<?> c) { return applicationcontext.getbean(c); } }); you need applicationcontext either field or final local variable work in java 7. note @ time of writing, java 7 not publicly supported oracle.
Comments
Post a Comment