废话不多说,重点是ioc接口
(1)SpringIocProvider.java
在这里:https://github.com/nutzam/nutzmore/blob/master/src/org/nutz/integration/spring/SpringIocProvider.java
(2)在nut的主模块中声明IocProvider即可,
import org.nutz.integration.spring.SpringIocProvider; import org.nutz.mvc.annotation.Encoding; import org.nutz.mvc.annotation.Fail; import org.nutz.mvc.annotation.IocBy; import org.nutz.mvc.annotation.Modules; import org.nutz.mvc.annotation.Ok;
@Ok("json") @Fail("json") @IocBy(type=SpringIocProvider.class,args={}) @Modules(value={MainModule.class},scanPackage=true) @Encoding(input="UTF-8",output="UTF-8") public class MainModule { }
这样,需要查找bean时,就调用SpringIocProvider,由它负责查找,
而后者是去spring的context里去查找的,
故实现了调用spring的bean~~
(3)在nutz的action类中,有一点需要注意。
如下:
@Component @InjectName public class UserWS {
@Autowired private UserService userService;
@At("/login") @Ok("void") public User login(String loginName, String password) { System.out.println("aaaa"); return toVo(userService.login(loginName, password)); } }
由于bean是spring管理了,所以组件@Component,注入@Autowired之类的注解都用spring的了。
但是@At,@OK什么的是nutz的,它们是MVC的注解,和IOC的注解不冲突~~
即nutz仍然负责url到方法的映射,
如此处/login映射到UserWS.login()方法,
那么访问/login时,找到UserWS,尝试去找它的bean,默认按userWS这个名字去找,
此时,是由SpringIocProvider去找的,由于用了@Component,所以找到了userWS这个bean,
注入userService等bean,然后调用它的login方法,
OK了。
nutz的mvc,结合spring的bean,就OK了
注意:@InjectName是nutz的注解,这个是需要的,没有这个,nutz不会去找bean,而是new了一个,就不对了。
(4)SpringIocProvider.java的代码如下:
package org.nutz.integration.spring;
import org.nutz.ioc.Ioc; import org.nutz.ioc.IocException; import org.nutz.ioc.annotation.InjectName; import org.nutz.lang.Lang; import org.nutz.lang.Strings; import org.nutz.mvc.IocProvider; import org.nutz.mvc.NutConfig; import org.springframework.context.ApplicationContext; import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.web.context.WebApplicationContext;
/** * 简单实现Nutz.IoC-Spring桥 * <p/> * Need Spring 2.0 or later * * @author wendal(wendal1985@gmail.com) * */ public class SpringIocProvider implements IocProvider, Ioc {
protected ApplicationContext applicationContext;
public Ioc create(NutConfig config, String[] args) { if (config == null || Lang.length(args) > 0) applicationContext = new ClassPathXmlApplicationContext(args); else applicationContext = (ApplicationContext) config.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); return this; }
public void depose() { if (applicationContext != null) { applicationContext.publishEvent(new ContextClosedEvent(applicationContext)); applicationContext = null; } }
@SuppressWarnings("unchecked") public <T> T get(Class<T> type, String name) { return (T) applicationContext.getBean(name, type); }
public String[] getNames() { return applicationContext.getBeanDefinitionNames(); }
public boolean has(String name) { return applicationContext.containsBean(name); }
public void reset() { applicationContext.publishEvent(new ContextRefreshedEvent(applicationContext)); }
@SuppressWarnings("unchecked") @Override public <T> T get(Class<T> classZ) throws IocException { InjectName injectName = classZ.getAnnotation(InjectName.class); if (injectName != null && !Strings.isBlank(injectName.value())) return (T) applicationContext.getBean(injectName.value()); return (T) applicationContext.getBean(applicationContext.getBeanNamesForType(classZ)[0]); } }
启动时,会调用create方法,
<1> 如果主模块中是 @IocBy(type=SpringIocProvider.class,args={})
即args是空的,那么走的是else分支,从config里直接把spring的context取出来了。
此种情况,spring是单独在web.xml中声明的,如
<!--Spring ApplicationContext 载入--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> 即spring单独启动,然后nutz直接取它的context。
<2>如果主模块中是类似这样: @IocBy(type=SpringIocProvider.class,args={"classpath*:/applicationContext.xml"}) 即args不为空,则走if分支,直接new了一个ClassPathXmlApplicationContext,
此时,就是nutz启动了spring,web.xml中就不需要spring的声明了。
|