作者:jxxpoo | 来源:互联网 | 2023-05-19 16:44
原理理解:spring自动注入对象是通过创建一个BeanFactory并传入applicationContext配置文件对象,然后调用BeanFactory的getBean方法来实
框架:spring+struts2
spring负责对象管理,MVC;自动装配由struts2完成 (bean定义+getter/setter方法);
项目中用到了通过反射途径调用相应的业务模块的逻辑。controller接收http请求后,根据请求参数获得业务代码和方法参数,到.xml配置文件中读取相应的类名,方法名,参数类型列表,调用ReflectASM.jar(高效反射工具)中的
public static Object AsmMethodRefUtil.invokeAsmFunc(String className, String methodName, Object[] paramValues, Class>[] paramTypes);
方法。该工具根据类名生成相应的对象,调用方法,传入参数列表并返回所调用的方法返回值。
我的问题是:需要在反射生成的对象中注入一个spring bean定义的对象,然而被注入的容器类本身不是spring bean组件,怎么办?
原理理解:
spring自动注入对象是通过创建一个BeanFactory并传入applicationContext配置文件对象,然后调用BeanFactory的getBean方法来实现相互依赖的对象获取和装配的。如果被注入的容器没有在spring bean中配置,而是通过反射途径生成,不能获取BeanFactory,就意味着不能进行自动注入。
如果在组件上实现一些spring提供的接口,如BeanFactoryAware、ApplicationContextAware,就可以手动方式获取BeanFactory,实现依赖注入。
在两个网页找到了共3种方法。
https://my.oschina.net/zhukp/blog/170855
http://www.cnblogs.com/Johness/archive/2012/12/25/2833010.html
我使用了第一个网页的第一种方法。
被注入的容器类需要extends BaseAutoAware。因为我的组件已经继承一个父类,我把其中的代码移植到了组件继承的父类中。
public class BaseWebService { public BaseSfqxWebService() { ((AutowireCapableBeanFactory)retrieveBeanFactory()) .autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true); }private BeanFactory retrieveBeanFactory() { BaseLocator bl=new BaseLocator(); BeanFactory f = bl.getFactory(); return f;}}
BaseLocator类,实现BeanFactoryAware接口,获取BeanFactory对象:
(需要spring-beans-XXX.jar)
public class BaseLocator implements BeanFactoryAware {private static BeanFactory factory = null; private static BaseLocator baselocator = null;@Override public void setBeanFactory(BeanFactory f) throws BeansException { factory = f; } public BeanFactory getFactory(){ return factory; } public static BaseLocator getInstance() { if (baselocator == null) baselocator = (BaseLocator) factory.getBean("baseLocator"); return baselocator; } }
在spring bean里做个配置
其中getInstance()方法作者大约是漏掉了,所以一开始出现了组件父类中retrieveBeanFactory()方法返回BeanFactory为null的情况,搜索后终于找到原因,于是加上。
被注入的容器子类采用getter/setter方法注入。
public class MyLoginWebService extends BaseWebService {private IUserService userService;public MyLoginWebService() {super();System.out.println(userService);}public IUserService getUserService() {return userService;}public void setUserService(IUserService userService) {this.userService = userService;} }
获取到的userService终于不为null了。
成功。
源码: 码云