论坛首页 Java企业应用论坛

整了2天的aop-spring2

浏览 9337 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-07-16   最后修改:2009-03-30
项目的日志部分由我负责,哎,本来以为spring2的aop能有多难,spring1的会了,2的肯定也手到擒来,没想到,就这个整整花了我2天的时间才摆平,都崩溃了.
下面简单地写下代码和配置:
@Transactional          //spring事务的支持
@Aspect                 //声明切面
public class LogService {
	private ApamLogDAO apamLogDAO;    //依赖注入dao,为节省版面就省略get,set了
	private ApamLog apamLog;          //声明日志的model类
	private Asppoi asppoi;            
	private Account account;

	// insert切入点
	// 这里的execution表达式是最复杂的部分,其实不难,主要是没有什么文档能把描述得很详细,连spring2的官方文档也只是概括地点了下	
	@Pointcut("execution(* com.olemap.apam.dao.AsppoiDAO.save(..))")
	public void PointcutSave() {
	}

	// insert通告
	@AfterReturning(pointcut = "PointcutSave()", returning = "status")
	public void AdviceSave(ProceedingJoinPoint joinPoint, Object status) {
		asppoi = (Asppoi) joinPoint.getArgs()[0];
		account = (Account) joinPoint.getArgs()[1];
		apamLog = new ApamLog();
		apamLog.setAccount(account);
		apamLog.setAction("insert");
		apamLog.setAsppoi(asppoi);
		apamLog.setStatus(Byte.parseByte(status.toString()));
		apamLog.setTime(new Date());
		apamLogDAO.save(apamLog);
	}
}

另外在spring的配置文件里,需要加上
<aop:aspectj-autoproxy proxy-target-class="true"/>


下面慢慢来解释:
一.spring2支持的增强类型:
before  after  afterReturning  afterThrowing  around

光名字就很好理解了,主要就是after,afterReturning的区别,在我这个模块上,我用了afterReturning,它可以让你的增强(advise)可以获得切入点的返回值.

二.签名语法:
call/execution/withincode(MethodPart)-方法调用/方法执行/在方法体内,MethodPart代表方法签名,execution较常用  (call我用了,但是始终报错,还没能试出它的用法)
MethodPart的语法结构是
[Modifier] Type [ClassType.] methodName(ArgumentType1...N...) [throws ExceptionType]
public void com.olemap.apam.dao.TestDAO.save(..) throws Exception

上面的语法是对应的,需要注意的是
1.加中括号的就是可选的部分
2.'..'是指所有的参数类型
3.可以用*来代表泛指

三.获得原方法形参的方法ProceedingJoinPoint
org.aspectj.lang.ProceedingJoinPoint表示连接点对象,通过getArgs()可以获得个连接点方法参数的数组

四.获得切入点方法返回值
在afterReturning那设置returning属性,并加在增强方法的形参处

除了注解实现外,另外还有xml文件配置,aspect语言2种方法实现,我会进一步去研究的.

以上是我这2天的成果,一次又一次的错误磨出来的,假如有什么错误或者有什么更好的方法,希望您指点下我.
   发表时间:2008-07-16  
AOP主要是概念一大堆,实际哪个小例子一看就会。

我现在就是随手带着demo,没有demo我还是要配很久
0 请登录后投票
   发表时间:2008-07-16  
d8111 写道
AOP主要是概念一大堆,实际哪个小例子一看就会。

我现在就是随手带着demo,没有demo我还是要配很久

to d8111
  你所指的demo是什么样的,可否共享一下。
0 请登录后投票
   发表时间:2008-07-17  
有个demo当然不错,不过过于简单的demo网上到处都是,没有什么实用价值,不知道1楼的朋友,你的是什么demo,能不能贴出来看看.
很简单的demo,签名语法肯定不全,这还是需要在实践中来摸索的
0 请登录后投票
   发表时间:2008-07-17  
为什么不直接使用
org.apache.commons.logging.Log;
org.apache.commons.logging.LogFactory;

我比较懒,没什么要求,就用这两个。
0 请登录后投票
   发表时间:2008-07-17  
因为项目经理需要把部分操作储存到数据库中,这样容易查看点,我也是奉命行事啊,哈哈!当然项目中也使用了common-logging.
0 请登录后投票
   发表时间:2008-07-21  
他的demo很明显,就是自己或者公司以前写的一些小东西。主要的配置文件和一些关键的代码。
0 请登录后投票
   发表时间:2008-07-31  
能给小弟一个简单的例子么?
0 请登录后投票
   发表时间:2008-08-07  
lkjust08 写道
能给小弟一个简单的例子么?

大体思路如下:通过Annotation的方式标明某些方法需要AOP操作。
1.写一个自定义的Annotation:
package com.jacky.menu.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.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BusinessLogger {
   String value() default "Operation";
}


2.写你的AOP处理类:
第一种方式,使用Spring Framework提供的AfterReturningAdvice接口
package com.jacky.menu.aop;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

import com.jacky.menu.annotation.BusinessLogger;

public class BusinessAdvisor implements AfterReturningAdvice {

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.aop.AfterReturningAdvice#afterReturning(java.lang.Object,
	 *      java.lang.reflect.Method, java.lang.Object[], java.lang.Object)
	 */
	public void afterReturning(Object returnValue, Method method,
			Object[] args, Object target) throws Throwable {
		Method implMethod = target.getClass().getMethod(method.getName(),
				method.getParameterTypes());
		BusinessLogger annoLogger = implMethod
				.getAnnotation(BusinessLogger.class);
		String operation = annoLogger != null ? annoLogger.value() : "null";
		StringBuilder tmp = new StringBuilder();
		tmp.append(operation).append(":").append(target.getClass().getName())
				.append(".").append(method.getName());
		System.out.println(tmp.toString());
	}

}

第二种方式,使用AspectJ来实现Advisor:
package com.jacky.menu.aop;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;


@Aspect
public class AspectJTest {
	
	@AfterReturning("@annotation (com.jacky.menu.annotation.BusinessLogger)")
	public void afterReturning(){
		System.out.println("Aop invoked!!!");
	}
}


3.需要调用AOP处理的业务逻辑方法
	@BusinessLogger("Generate Tree Root")
	public Menu generateMenuTreeRoot() {
		return menuDao.getRootMenu();
	}


4.applicationContext.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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
		xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee"
		xmlns:tx="http://www.springframework.org/schema/tx"
		xsi:schemaLocation="
			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
			http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
			http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
			
	<!-- 组件查找策略 -->
	<context:component-scan base-package="com.jacky.menu.bus" />
	
	<!-- 启用注解,Spring Annotation需使用 -->
	<context:annotation-config/>
	
	<!-- 使用Spring AOP方式实现AOP -->
	<aop:config proxy-target-class="true">
		<!-- 切入点定义为所有带有@BusinessLogger注解的业务逻辑方法 -->
		<aop:pointcut id="alterPoint"
				expression="@annotation(com.jacky.menu.annotation.BusinessLogger)"/>
		
		<!-- After Returning通知 -->
		<aop:advisor advice-ref="businessAdvisor" id="afterBusAdvisor" pointcut-ref="alterPoint"/>
	</aop:config>
	
	<!-- AOP Advisor 实现类 -->
	<bean id="businessAdvisor" class="com.jacky.menu.aop.BusinessAdvisor"></bean>
	
	<!-- 使用AspectJ方式 -->
	<aop:aspectj-autoproxy proxy-target-class="true"/>
	
	<!-- advisor using aspectJ -->
	<bean class="com.jacky.menu.aop.AspectJTest" />
</beans>


5.输出结果:
对于第一种Advisor实现方式:
Generate Tree Root:com.jacky.menu.bus.impl.MenuManagerImpl.generateMenuTreeRoot
对于第二种Advisor实现方式:
Aop invoked!!!
1 请登录后投票
   发表时间:2008-08-20  
@Aspect,spring的 切面一般是写入xml好,还是用annotation写在页面好
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics