`

利用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。

 

2
3
分享到:
评论
1 楼 eric_hwp 2013-01-07  
大侠,求下载地址

相关推荐

    Spring AOP配置源码

    package com.spring.dao; import org.springframework.stereotype.Component; @Component("userDAO") public class UserDao { public void say() { System.out.println("say method is called"); } public ...

    Spring中文帮助文档

    12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用...

    Spring API

    12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用...

    Spring.3.x企业应用开发实战(完整版).part2

    Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。  Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...

    Spring3.x企业应用开发实战(完整版) part1

    Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。  Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...

    spring_MVC源码

    本文主要介绍使用注解方式配置的spring mvc,之前写的spring3.0 mvc和rest小例子没有介绍到数据层的内容,现在这一篇补上。下面开始贴代码。 文中用的框架版本:spring 3,hibernate 3,没有的,自己上网下。 先说...

    基于SpringMVC+Hibernate4的考勤管理系统+.zip

    spring-aop-4.0.0.RELEASE.jar 使用Spring 的AOP 特性时所需的类和源码级元数据支持 spring-aspects-4.0.0.RELEASE.jar 提供对AspectJ的支持,以便可以方便的将面向方面的功能集成进IDE中 spring-beans-4.0.0....

    springmybatis

    其实还有更简单的方法,而且是更好的方法,使用合理描述参数和SQL语句返回值的接口(比如IUserOperation.class),这样现在就可以至此那个更简单,更安全的代码,没有容易发生的字符串文字和转换的错误.下面是详细...

    SpringMVC-SSH全注解

    &lt;bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"&gt; &lt;value&gt;com.org.core.entity&lt;/value&gt; ${hibernate....

    spring-framework-reference-4.1.2

    3. New Features and Enhancements in Spring Framework 4.0 ............................................ 17 3.1. Improved Getting Started Experience .........................................................

    客户关系管理系统框架搭建(二)

    * 搭建spring和hibernate * 创建beans.xml文件,放置在src下 * 引入命名空间 bean tx context aop &lt;beans xmlns="http://www.springframework.org/schema/beans" xmlns:context=...

    SpringShiro分布式缓存版

    class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor" /&gt; class="org.apache.shiro.spring.security.interceptor....

    spring-framework-reference4.1.4

    3. New Features and Enhancements in Spring Framework 4.0 ............................................ 17 3.1. Improved Getting Started Experience .........................................................

    一个支持annotation的SSH整合示例项目

    │ │ │ ├─aop │ │ │ │ GedaAuthenticationCheck.java │ │ │ │ SystemArchitecture.java │ │ │ │ │ │ │ └─service │ │ │ └─login │ │ │ │ LogInService.java │ │ │ │ ...

Global site tag (gtag.js) - Google Analytics