JFinal源码解析二:AOP的实现

1、首先介绍下JFinal中AOP的主角Interceptor接口:

public interface Interceptor {
	void intercept(Invocation inv);
}

在源码中已经有了多种功能的实现,如Validator(校验功能)、Tx(事务功能),因此我们可以根据实际的需求来实现该接口就可以了。

2、用户需要实现一个继承JFinalConfig的配置类,实现void configInterceptor(Interceptors me)该方法来导入全局的Interceptor

public class MyJFinalApp extends JFinalConfig {

	@Override
	public void configConstant(Constants arg0) {
		arg0.setDevMode(true);

		arg0.setEncoding("utf-8");

		arg0.setViewType(ViewType.JSP);

	}

	@Override
	public void configHandler(Handlers arg0) {
		arg0.add(new ContextPathHandler("basePath"));
	}


	@Override
	public void configInterceptor(Interceptors arg0) {
		arg0.add(new LogInterceptor());        //添加全局拦截器

	}

	@Override
	public void configPlugin(Plugins arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void configRoute(Routes arg0) {
		arg0.add("/", IndexControllerJFinal.class);

	}

3、在JFinal类初始化时会调用initActionMapping()方法

public final class JFinal {
	
	private Constants constants;
	private ActionMapping actionMapping;
	private Handler handler;
	private ServletContext servletContext;
	private String contextPath = "";
	private static IServer server;
	
	private static final JFinal me = new JFinal();
	
	private JFinal() {
	}
	
	public static JFinal me() {
		return me;
	}
	
	boolean init(JFinalConfig jfinalConfig, ServletContext servletContext) {
		this.servletContext = servletContext;
		this.contextPath = servletContext.getContextPath();
		
		initPathUtil();
		
		Config.configJFinal(jfinalConfig);	// start plugin and init log factory in this method
		constants = Config.getConstants();
		
		initActionMapping();
		initHandler();
		initRender();
		initOreillyCos();
		initTokenManager();
		
		return true;
	}
	.
	.
	.
}

4、在initActionMapping方法中调用actionMapping.buildActionMapping()方法。

private void initActionMapping() {
		actionMapping = new ActionMapping(Config.getRoutes(), Config.getInterceptors());
		actionMapping.buildActionMapping();
	}

5、关键代码就是这个buildActionMapping()方法:

void buildActionMapping() {
		mapping.clear();
		Set<String> excludedMethodName = buildExcludedMethodName();
		InterceptorManager interMan = InterceptorManager.me();
		
		for (Entry<String, Class<? extends Controller>> entry : routes.getEntrySet()) {
			Class<? extends Controller> controllerClass = entry.getValue();
			Interceptor[] controllerInters = interMan.createControllerInterceptor(controllerClass);    //创建每个类(controller)的拦截器
			
			boolean sonOfController = (controllerClass.getSuperclass() == Controller.class);
			Method[] methods = (sonOfController ? controllerClass.getDeclaredMethods() : controllerClass.getMethods());
			for (Method method : methods) {
				String methodName = method.getName();
				if (excludedMethodName.contains(methodName) || method.getParameterTypes().length != 0)
					continue ;
				if (sonOfController && !Modifier.isPublic(method.getModifiers()))
					continue ;
				
				Interceptor[] actionInters = interMan.buildControllerActionInterceptor(controllerInters, controllerClass, method);    //创建每个action的对应拦截器
				String controllerKey = entry.getKey();
				
				ActionKey ak = method.getAnnotation(ActionKey.class);
				String actionKey;
				if (ak != null) {
					actionKey = ak.value().trim();
					if ("".equals(actionKey))
						throw new IllegalArgumentException(controllerClass.getName() + "." + methodName + "(): The argument of ActionKey can not be blank.");
					
					if (!actionKey.startsWith(SLASH))
						actionKey = SLASH + actionKey;
				}
				else if (methodName.equals("index")) {
					actionKey = controllerKey;
				}
				else {
					actionKey = controllerKey.equals(SLASH) ? SLASH + methodName : controllerKey + SLASH + methodName;
				}
				
				Action action = new Action(controllerKey, actionKey, controllerClass, method, methodName, actionInters, routes.getViewPath(controllerKey));
				if (mapping.put(actionKey, action) != null)
					throw new RuntimeException(buildMsg(actionKey, controllerClass, method));
			}
		}
		
		// support url = controllerKey + urlParas with "/" of controllerKey
		Action action = mapping.get("/");
		if (action != null)
			mapping.put("", action);
	}

            1)首先调用InterceptorManager类中createControllerInterceptor()方法,来创建每个controller的Interceptors(通过@Before)。createControllerInterceptor方法最终会调用createInterceptor方法

public Interceptor[] createControllerInterceptor(Class<? extends Controller> controllerClass) {
                //通过注解来获取对应controller的class基本的拦截器
		return createInterceptor(controllerClass.getAnnotation(Before.class));    
	}
	
	
public Interceptor[] createInterceptor(Class<? extends Interceptor>[] interceptorClasses) {
		if (interceptorClasses == null || interceptorClasses.length == 0) {
			return NULL_INTERS;
		}
		
		Interceptor[] result = new Interceptor[interceptorClasses.length];
		try {
			for (int i=0; i<result.length; i++) {
				result[i] = singletonMap.get(interceptorClasses[i]);
				if (result[i] == null) {
					result[i] = (Interceptor)interceptorClasses[i].newInstance();
					singletonMap.put(interceptorClasses[i], result[i]);
				}
			}
			return result;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}


            2)获取每个controller中的action方法,再创建每个方法的Interceptors,并通过@Clear注解去掉需要忽略的Interceptors。

6、最终把每个action的所有Interceptors通过Action类的构造函数传入Action对象中(buildActionMapping方法中)。

你可能感兴趣的:(AOP,源码,jFinal)