关于jfinal springPlugin自动注入

    最近学习jfinal和spring整合,总觉的IocInterceptor实现注入有点麻烦,就自己通过ControllerFactory实现注入。

package com.demo.jfinal.core;

import com.jfinal.core.Controller;
import com.demo.common.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * ControllerFactory
 */
public class ControllerFactory extends com.jfinal.core.ControllerFactory {

    private ThreadLocal<Map<Class<? extends Controller>, Controller>> buffers = new ThreadLocal<Map<Class<? extends Controller>, Controller>>() {
        protected Map<Class<? extends Controller>, Controller> initialValue() {
            return new HashMap<Class<? extends Controller>, Controller>();
        }
    };

    public Controller getController(Class<? extends Controller> controllerClass) throws InstantiationException, IllegalAccessException {
        Controller ret = buffers.get().get(controllerClass);
        if (ret == null) {
            ret = controllerClass.newInstance();
            autoInject(ret);
            buffers.get().put(controllerClass, ret);
        }
        return ret;
    }

    /**
     * 自动注入
     * @param ret controller
     */
    public void autoInject(Controller ret) {

        Field[] fields = ret.getClass().getDeclaredFields();
        for (Field field : fields) {
            Object bean = null;
            if (field.isAnnotationPresent(Autowired.class)) {
                try {
                    bean = BeanFactory.getBean(field.getName());
                } catch (Exception e) {
                }
                if (null == bean) {
                    try {
                        bean = BeanFactory.getBean(field.getType());
                    } catch (Exception e) {
                    }
                }
                if (null == bean) {
                    Autowired annotation = field.getAnnotation(Autowired.class);
                    if (annotation.required()) {
                        throw new RuntimeException(String.format(
                                "Error creating bean with name '%s': Injection of autowired dependencies failed.",
                                field.getName()));
                    }
                }
            } else if (field.isAnnotationPresent(Resource.class)) {
                Resource annotation = field.getAnnotation(Resource.class);
                bean = BeanFactory.getBean(annotation.name().trim().length() == 0 ? field.getName() : annotation.name());
            } else
                continue;
            try {
                if (bean != null) {
                    field.setAccessible(true);
                    field.set(ret, bean);
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}

    BeanFactory可以通过实现ApplicationContextAware注入ApplicationContext,也可以通过springPlugin直接注入到ControllerFactory。

评论区

lyh061619

2017-12-22 18:25

用这招,兄弟你的姿势绝对正确,这招用好,你就知道JFinal设计的艺术

JFinal

2017-12-22 18:26

通过 ControllerFactory 来让 jfinal 整合 spring 是目前最好方案,用拦截器的话,可以被 @Clear 注解清除掉

代码十分简洁,感谢你的分享

花火丶

2018-01-12 15:01

这才是正确姿势,拿走了,谢谢

shihy

2018-01-24 16:45

com.jfinal.core.ControllerFactory 这个类怎么没有找到?

shigy_007

2018-04-10 17:10

BeanFactory怎么没贴出来,能找到嘛?

adonho88

2018-04-16 16:02

@shigy_007
public class BeanFactory implements ApplicationContextAware {

private static ApplicationContext ctx;

public static Object getBean(String name) {
return ctx.getBean(name);
}

public static T getBean(Class requiredType) {
return ctx.getBean(requiredType);
}

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ctx = applicationContext;
}
}
在spring配置里定义BeanFactory即可,

adonho88

2018-04-16 16:02

@shihy 可能是版本不一样,我用的是jfinal3.3

shigy_007

2018-04-24 11:43

@adonho88 非常非常感谢

热门分享

扫码入社