配置文件内容自动注入

作用:配置文件中的配置信息不再需要通过Propkit.get(xxx)的方式获取,可以像对象那样自动注入

支持Long Integer Boolean String 类型的注入

示例:

@ControllerMapping("/authen")
public class AuthenticationController extends BaseController {
	@Inject
	private AuthenticationService authenticationService;
	
	// 读取配置文件的配置信息
	@Value("test")
	private Boolean test;
	/**
	 * 认证
	 */
	@NoNeedLogin
	public void getToken(@NotNull(message="用户名为空!")String userName, @NotNull(message="密码为空!")String password) {
		if(test) {
			String token = this.authenticationService.getToken(userName, password);
			renderResult(token);
		}else {
			renderResult(null);
		}
		
	}
}

实现:

定义自己的AopFactory,覆盖其中的 doInject 方法

package com.future.common.jfinalcustom;

import java.lang.reflect.Field;

import com.future.common.annotation.Value;
import com.jfinal.aop.AopFactory;
import com.jfinal.aop.Inject;
import com.jfinal.core.Controller;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.validate.Validator;

public class FutureAopFactory extends AopFactory {
	/**
	 * 增加对配置文件值的注入
	 */
	@Override
	protected void doInject(Class<?> targetClass, Object targetObject) throws ReflectiveOperationException {
		targetClass = getUsefulClass(targetClass);
		Field[] fields = targetClass.getDeclaredFields();
		if (fields.length != 0) {
			for (Field field : fields) {
				Class<?> fieldInjectedClass = null;
				Inject inject = field.getAnnotation(Inject.class);
				if(inject != null) {
					 fieldInjectedClass = inject.value();
					if (fieldInjectedClass == Void.class) {
						fieldInjectedClass = field.getType();
					}
					
					Object fieldInjectedObject = doGet(fieldInjectedClass);
					field.setAccessible(true);
					field.set(targetObject, fieldInjectedObject);
				}else {
					Value value = field.getAnnotation(Value.class);
					if(value == null || StrKit.isBlank(value.value())) {
						continue;
					}
					
					String configName = value.value();
					fieldInjectedClass = field.getType();
					field.setAccessible(true);
					if (fieldInjectedClass == String.class) {
						field.set(targetObject, PropKit.get(configName));
					} else if (fieldInjectedClass == Boolean.class || fieldInjectedClass == boolean.class) {
						field.set(targetObject, PropKit.getBoolean(configName));
					} else if (fieldInjectedClass == Integer.class || fieldInjectedClass == int.class) {
						field.set(targetObject, PropKit.getInt(configName));
					} else if (fieldInjectedClass == Long.class || fieldInjectedClass == long.class) {
						field.set(targetObject, PropKit.getLong(configName));
					} else {
						throw new RuntimeException("@Value 注解只支持Long Integer Boolean String 类型的数据注入!");
					}
					
				}
				
				
				
			}
		}
		
		// 是否对超类进行注入
		if (injectSuperClass) {
			Class<?> c = targetClass.getSuperclass();
			if (c != Controller.class && c != Object.class && c != Validator.class && c != Model.class && c != null) {
				doInject(c, targetObject);
			}
		}
	}
}

定义注解,标识该filed需要注入配置信息

package com.future.common.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {
	String value();
}

让jfinal使用自定义AopFactory

在 MainConfig.java  configConstant 中增加下面的代码

AopManager.me().setAopFactory(new FutureAopFactory());


具体代码详见:

https://gitee.com/git_zhanglong/future

该工程持续集成jfinal相关解决方案

其他方案欢迎关注项目

Future

关注我的公众号,免费获取Java + Jfinal学习视频

image.png


评论区

yunqi

2019-12-03 17:25

private static ApplicationContext applicationContext;

public static T getBean(String beanName) {
if(applicationContext.containsBean(beanName)){
return (T) applicationContext.getBean(beanName);
}else{
return null;
}
}

能不能扩展一下类似spring的这种 通过一个beanName 获取到 bean 对象呢 比如 传入 user 获得 com.xx.user.class

快乐的蹦豆子

2019-12-03 17:45

Class cla = Class.forName(beanName包名的全名) 获取class 对象, 然后 Aop.get(cla ) 就可以了

JFinal

2019-12-06 23:46

挺好的分享,如果走单例模式,这个扩展对性能没有影响,赞

zsw大伟

2019-12-09 11:56

如果被注入的对象是个接口,目前无法自动找到实现类而自动注入

快乐的蹦豆子

2019-12-09 16:40

@zsw大伟 当然也可以实现了,无非就是构造一个容器把映射关系放里面,然后再使用。

zzutligang

2019-12-10 11:53

@快乐的蹦豆子,@ControllerMapping("/authen")你代码里这个注解哪里提供的?一直在找这种玩法。

快乐的蹦豆子

2019-12-10 14:44

@zzutligang 看我gitee的代码,自己实现的。

zzutligang

2019-12-12 09:07

@快乐的蹦豆子,如果我想用这个ControllerMapping注解,是只要把ControllerMapping.java合并到我的项目里就行了嘛?我看看代码除了controller里引用过,也没有见其他和ControllerMapping.java相关的代码

快乐的蹦豆子

2019-12-16 16:56

@zzutligang ControllerScan.java 才是真正扫描的代码,ControllerMapping只是一个注解,他们两个都需要,然后configRoute 中增加 me.add(new ControllerScan());

热门分享

扫码入社