Jfinal集成Spring插件

最近公司使用Jfinal开发项目,不知道什么原因Jfinal和其他的几个插件集成的时候,事物管理并不那么随心,所以就选择了Spring作为Jfinal的插件来管理事物.废话不多说,直接上代码.

public class MyConfig extends JFinalConfig{

	@Override
	public void configConstant(Constants me) {
		IocKit.processJFinalConfig(this);
		loadPropertyFile("db.properties");
		me.setEncoding("UTF-8");
		me.setDevMode(getPropertyToBoolean("devMode", true));
	}

	@Override
	public void configRoute(Routes me) {
		System.out.println("configRoute");
		me.add("/blog", BlogController.class);
	}

	@Override
	public void configPlugin(Plugins me) {
		SpringPlugin springPlugin = new SpringPlugin("classpath*:spring/applicationContext-*.xml");
		me.add(springPlugin);
		SpringDataSourceProvider prov = new SpringDataSourceProvider(springPlugin);
		// 配置ActiveRecord插件,将jfinal的事物交给Spring管理
		ActiveRecordPlugin arp = new ActiveRecordPlugin(prov);
		me.add(arp);
		arp.addMapping("system_admin", SystemAdmin.class);
		
	}

	@Override
	public void configInterceptor(Interceptors me) {
		System.out.println("configInterceptor");
	}

	@Override
	public void configHandler(Handlers me) {
		System.out.println("configHandler");
	}

	@Override
	public void configEngine(Engine me) {
		System.out.println("configEngine");
	}

}

IocKit.java

public class IocKit {

	// ioc @Inject @Value @Autowired
	static AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor;
	// ioc @Resource
	static CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor;

	public static AutowiredAnnotationBeanPostProcessor getAutowiredAnnotationBeanPostProcessor() {
		Assert.notNull(autowiredAnnotationBeanPostProcessor,
				"The main autowiredAnnotationBeanPostProcessor is null, initialize SpringPlugin first");
		return autowiredAnnotationBeanPostProcessor;
	}

	public static CommonAnnotationBeanPostProcessor getCommonAnnotationBeanPostProcessor() {
		Assert.notNull(commonAnnotationBeanPostProcessor,
				"The main commonAnnotationBeanPostProcessor is null, initialize SpringPlugin first");
		return commonAnnotationBeanPostProcessor;
	}

	// --------------------------------------------------
	// JFinalConfig
	// --------------------------------------------------

	/**
	 * @Title: 处理 JFinalConfig
	 */
	public static void processJFinalConfig(JFinalConfig finalConfig) {
		ApplicationContext ctx = org.springframework.web.context.support.WebApplicationContextUtils
				.getWebApplicationContext(JFinal.me().getServletContext());
		processJFinalConfig(finalConfig, ctx);
	}

	/**
	 * @Title: 处理 JFinalConfig
	 */
	public static void processJFinalConfig(JFinalConfig jfinalConfig, ApplicationContext ctx) {
		Assert.notNull(ctx, "ApplicationContext not be null");
		Assert.notNull(jfinalConfig, "jfinalConfig not be null");
		AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = setBeanFactory(
				new AutowiredAnnotationBeanPostProcessor(), ctx);
		CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor = setBeanFactory(
				new CommonAnnotationBeanPostProcessor(), ctx);

		processInjection(jfinalConfig, commonAnnotationBeanPostProcessor, autowiredAnnotationBeanPostProcessor);
	}

	/**
	 * @Title: 注入 bean 调用
	 */
	public static void invokeForProcessInjection(Object invocation) {
		Invocation inv = as(invocation, Invocation.class);
		Controller controller = inv.getController();
		processInjection(controller);
		inv.invoke();
	}

	public static void processInjection(Object bean) {
		processInjection(bean, commonAnnotationBeanPostProcessor, autowiredAnnotationBeanPostProcessor);
	}

	// ---------------------------------------------------------
	// function
	// ---------------------------------------------------------

	static void init(ApplicationContext ctx) {
		autowiredAnnotationBeanPostProcessor = setBeanFactory(new AutowiredAnnotationBeanPostProcessor(), ctx);
		commonAnnotationBeanPostProcessor = setBeanFactory(new CommonAnnotationBeanPostProcessor(), ctx);
	}

	static <T extends BeanFactoryAware> T setBeanFactory(T beanPostProcessor, ApplicationContext ctx) {
		beanPostProcessor.setBeanFactory(ctx.getAutowireCapableBeanFactory());
		return beanPostProcessor;
	}

	static void processInjection(Object bean, CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor,
			AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor) {
		commonAnnotationBeanPostProcessor.postProcessPropertyValues(null, null, bean, null);
		autowiredAnnotationBeanPostProcessor.processInjection(bean);
	}
	
	// ----------------------------------------------------------------
	// as proxy
	// ----------------------------------------------------------------

	private final static Map<String, Method> methodCache = new HashMap<String, Method>(16);

	private static Method cachedMethod(Class<?> type, Method method) throws NoSuchMethodException {
		String name = method.getName();
		String key = type.getName() + "." + name;

		Method m = methodCache.get(key);

		if (m == null) {
			synchronized (methodCache) {
				m = methodCache.get(key);
				if (m == null) {
					Class<?>[] parameterTypes = method.getParameterTypes();
					try {
						// Actual method name matches always come first
						m = type.getMethod(name, parameterTypes);
					} catch (SecurityException ignore) {
						m = type.getDeclaredMethod(name, parameterTypes);
					}

					methodCache.put(key, m);
				}
			}
		}
		return m;
	}

	/**
	 * Create a proxy for the wrapped object allowing to typesafely invoke
	 * methods on it using a custom interface
	 *
	 * @param proxyType
	 *            The interface type that is implemented by the proxy
	 * @return A proxy for the wrapped object
	 */
	@SuppressWarnings("unchecked")
	private static <P> P as(final Object object, Class<P> proxyType) {
		final Class<?> clazz = object.getClass();

		final InvocationHandler handler = new InvocationHandler() {
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				Method m = cachedMethod(clazz, method);
				boolean accessible = m.isAccessible();
				try {
					if (!accessible) m.setAccessible(true);
					return m.invoke(object, args);
				} finally {
					m.setAccessible(accessible);
				}
			}
		};

		return (P) Proxy.newProxyInstance(proxyType.getClassLoader(), new Class[] { proxyType }, handler);
	}

	private static interface Invocation {
		void invoke();

		Controller getController();
	}
}

SpringDataSourceProvider.java

public class SpringDataSourceProvider implements IDataSourceProvider {
	
	private static final String proxyDsName = "proxyDataSource";

	private SpringPlugin springPlugin;
	
	private String beanName;

	public SpringDataSourceProvider(SpringPlugin springPlugin, String beanName) {
		this.springPlugin = springPlugin;
		this.beanName = beanName;
	}
	public SpringDataSourceProvider(SpringPlugin springPlugin) {
		this.springPlugin = springPlugin;
		this.beanName = proxyDsName;
	}

	public DataSource getDataSource() {
		ApplicationContext ctx = springPlugin.getApplicationContext();
		return (DataSource)ctx.getBean(beanName,TransactionAwareDataSourceProxy.class);
	}
}

SpringPlugin.java

private static boolean isStarted = false;
	private String[] configurations;
	private ApplicationContext ctx;
	
	public SpringPlugin() {}

	public SpringPlugin(ApplicationContext ctx) {
		this.setApplicationContext(ctx);
	}
	
	public SpringPlugin(String... configurations) {
		this.configurations = configurations;
	}

	public void setApplicationContext(ApplicationContext ctx) {
		Assert.notNull(ctx, "ApplicationContext can not be null.");
		this.ctx = ctx;
	}
	
	public ApplicationContext getApplicationContext() {
		return this.ctx ;
	}

	public boolean start() {
		if (isStarted) {
			return true;
		}else if (!isStarted && configurations != null){
			ctx = new FileSystemXmlApplicationContext(configurations);
		}else {
			ctx = new FileSystemXmlApplicationContext(PathKit.getWebRootPath() + "/WEB-INF/applicationContext.xml");
		}
		Assert.notNull(ctx, "ApplicationContext can not be null.");
		IocKit.init(ctx);
		return isStarted = true;
	}

	public boolean stop() {
		ctx = null;
		isStarted = false;
		return true;
	}
}

applicationContext-core.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
	    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xmlns:context="http://www.springframework.org/schema/context" 
		default-autowire="byName"
		xmlns:aop="http://www.springframework.org/schema/aop" 
		xmlns:p="http://www.springframework.org/schema/p"
		xmlns:tx="http://www.springframework.org/schema/tx" 
		xmlns:util="http://www.springframework.org/schema/util"
		xsi:schemaLocation="http://www.springframework.org/schema/aop 
							http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
							http://www.springframework.org/schema/beans 
							http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
							http://www.springframework.org/schema/util 
							http://www.springframework.org/schema/util/spring-util-3.2.xsd
							http://www.springframework.org/schema/tx 
							http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
							http://www.springframework.org/schema/context 
							http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    <!-- 引入配置文件 -->
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:db.properties"/>
    </bean>
    <!-- dataSource配置 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
          init-method="init" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="filters" value="log4j"/>
        <property name="maxActive" value="5"/>
        <property name="initialSize" value="1"/>
        <property name="maxWait" value="6000"/>
    </bean>
    
    <bean id="proxyDataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
	    <constructor-arg>
	        <ref bean="dataSource" />
	    </constructor-arg>
	</bean>
    
    <!-- 声明式事务的配置 -->
    <!-- 事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    	<property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 配置事务通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="delete*" propagation="REQUIRED" read-only="false" />
			<tx:method name="insert*" propagation="REQUIRED" read-only="false" />
			<tx:method name="update*" propagation="REQUIRED" read-only="false" />
			<tx:method name="find*" propagation="SUPPORTS" />
			<tx:method name="get*" propagation="SUPPORTS" />
			<tx:method name="select*" propagation="SUPPORTS" />
		</tx:attributes>
	</tx:advice>
	<!-- 把事务控制在Service层 -->
	<aop:config>
		<aop:pointcut id="pointcut" expression="execution(public * cn.minions.testSpring.Service.impl.*.*(..))" />
		<aop:advisor pointcut-ref="pointcut" advice-ref="txAdvice" />
	</aop:config>
	<context:component-scan base-package="cn.minions.testSpring" />
</beans>

完整测试项目的地址:https://gitee.com/fhcspring/jfinal-spring

测试环境还集成了activiti mybatis

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值