利用spring AOP和Annotation来简化DAO实现

通常在数据库DAO层的查询中,我们会定义一个DAO接口,而在实现中我们只是拼接查询参数并且指定一个ibatis的sqlmap中的sqlid进行查询,

Dao的实现很类似,而且非常简单,其实可以简化这种的实现,不需要这些实现代码,下面我们通过annotation机制来简化这块的实现。

比如

public class TestDaoImpl extends SqlMapClientDaoSupport implements TestDao {
    @Override
    public int updateBrandOfferStatusByBrandMemberId(Long brandMemberId, String operator, String status) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("brandMemberId", brandMemberId);
        map.put("operator", operator);
        map.put("status", status);
        return this.getSqlMapClientTemplate().update("BRANDOFFER.UPDATE-BRANDOFFER-BY-BRANDMEMBERID", map);
    }

    @Override
    public List<Long> queryOfferIdsByBrandMemberId(Long brandMemberId, Integer start, Integer end) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("brandMemberId", brandMemberId);
        map.put("start", start);
        map.put("end", end);
        return this.getSqlMapClientTemplate().queryForList("BRANDOFFER.SELECT-OFFERIDLIST-BY-BRANDMEMBERID", map);
    }
 ......
}

首先,我们使用建立一个spring的工程,依赖如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

	<modelVersion>4.0.0</modelVersion>
	<groupId>mySpringWeb</groupId>
	<artifactId>springDemo</artifactId>
	<packaging>jar</packaging>
	<version>1.0.0-SNAPSHOT</version>

	<name>Started with Laurel</name>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>3.2.0.RELEASE</version>
		</dependency>

	</dependencies>

	<repositories>
		<repository>
			<id>springsource-repo</id>
			<name>SpringSource Repository</name>
			<url>http://repo.springsource.org/release</url>
		</repository>
	</repositories>

</project>


我们定义两个annotation

DAO是用来加在DAO接口的方法上的annotaion,可以通过name指定ibatis中的sql id,这个annotation可以添加type之类的参数,可以用来指定dao查询的类型,inserti,update,query,delete等类型。

package mySpringWeb;

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

@Retention(RetentionPolicy.RUNTIME)    
@Inherited
@Target({ ElementType.METHOD, ElementType.TYPE})
public @interface Dao {
	String name() default "[defaultMethod]";
}

DaoParam是用来在DAO方法的参数上加的annotation,用来指定ibatis查询map参数的构造,map的key名称

package mySpringWeb;

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

@Retention(RetentionPolicy.RUNTIME)    
@Inherited
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.LOCAL_VARIABLE, ElementType.PARAMETER})
public @interface DaoParam {
	String name() default "paramName";
}

然后定义一个DAO接口,里面有一个方法,

package mySpringWeb;

import java.util.List;

public interface MyDao {
	@Dao(name="MyDaoAnnotataion")
	public List<Object> query(@DaoParam(name="param1")String param1, @DaoParam(name="param2")int param2);
}

我们写一个空的DAO实现类,

package mySpringWeb;

import java.util.List;

public class MyDaoImpl implements MyDao{

	@Override
	public List<Object> query(@DaoParam(name="param1")String param1, @DaoParam(name="param2")int param2) {
		// TODO Auto-generated method stub
		return null;
	}

}

然后就是写一个spring AOP的 拦截器类了,

package mySpringWeb;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.core.annotation.AnnotationUtils;

public class MyIntercept implements MethodInterceptor{

	static{
		try {
			Class.forName("mySpringWeb.Dao");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		Dao dao = AnnotationUtils.findAnnotation(invocation.getMethod(), Dao.class);//递归查找该方法是否定义了这个annotation
		if(dao != null){
				List<String> list = new ArrayList<String>();
				list.add(dao.name());
				System.out.println(dao.name());
				//method name就是ibatis sqlid,这里可以注入一个dao,然后传入sqlid,执行返回
				System.out.println(invocation.getMethod().getName());
				Map<String,Object> paraMap = new HashMap<String,Object>();
				Annotation[][] annotations = invocation.getMethod().getParameterAnnotations();
				Object[] object = invocation.getArguments();
				for(int i = 0; i < annotations.length;i++){
					for(Annotation an: annotations[i]){
						if(an.annotationType().isAssignableFrom(DaoParam.class)){
							System.out.println(an.toString());
							paraMap.put(((DaoParam)an).name(), object[i]);	
						}
					}
				}
				
				//dao查询参数map
				System.out.println(paraMap.toString());
				//这里ibatis sqlid和查询参数map都知道,那么就可以进行数据库查询,然后返回了,对于返回类型也可以通过定义返回的annotation进行返回参数类型的几种定义
				//当前这里需要注入spring的DAO的一个实现,这里根据annotation的类型和参数以及sqlid就可以进行数据库查询,然后返回,这里就比较简单了。
				
				return list;
		}
		System.out.println("go to here error");
		return null;
	}

}

再进行spring的bean xml配置,bean.xml,这里可以对多个DAO进行配置同一个拦截器,然后就可以统一处理了。


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.1.xsd
	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

	<bean id="mydao" class="mySpringWeb.MyDaoImpl" />
	<bean id="myintercept" class="mySpringWeb.MyIntercept" />
	<bean id="mydaobean" class=" org.springframework.aop.framework.ProxyFactoryBean">
		<property name="proxyInterfaces">
			<value>mySpringWeb.MyDao</value>
		</property>
		<property name="interceptorNames">
			<list>
				<value>myintercept</value>
				<value>mydao</value>
			</list>
		</property>
	</bean>

</beans>

写一个测试类:

package mySpringWeb;

import java.util.List;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
//	@Resource
//	private MyDao myDao;
//	
//	public void test(){
//		List<Object> list = myDao.query();
//		System.out.println(list);
//	}

	public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
		MyDao myDao = (MyDao) new ClassPathXmlApplicationContext("bean.xml").getBean("mydaobean");
		List<Object> list = myDao.query("test1", 1);
		System.out.println(list);
//		System.out.println(myDao.toString());
		
//		MyDao myDao1 =  (MyDao) Class.forName("mySpringWeb.MyDaoImpl").newInstance();  
//		Method[] methods = myDao1.getClass().getMethods();
//		for(Method method: methods){
//			Annotation[] annos = method.getAnnotations();
//			for(Annotation anno: annos){
//				System.out.println(anno.getClass().getName());
//			}
//		}
	}
}

输出:

MyDaoAnnotataion
query
@mySpringWeb.DaoParam(name=param1)
@mySpringWeb.DaoParam(name=param2)
{param1=test1, param2=1}
[MyDaoAnnotataion]

这种方式就可以简化DAO实现的一堆重复逻辑,通过在DAO 的interface中annotation定义好就可以了。

不过有个优化,不知道有没有办法不用定义每一个DAO的空实现类,应该是有办法的。具体的后面再研究。还有annotation如果直接通过invocation.getMethod().getAnnotation()是获取不到接口中定义的annotation的,必须得通过AnnotationUtils.findAnnotation(invocation.getMethod(), Dao.class);这个方法查询方法的annotation。


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值