spring AOP使用

      Spring AOP 无需使用任何特殊命令对 Java 源代码进行编译,它采用运行时动态地、在内存中临时生成代理类的方式来生成 AOP 代理。但在性能上相比较于编译是增强的AOP框架(AspectJ )稍差些。反编译spring AOP目标类的字节码,是没有发生改变的!

       

    Spring AOP 大致执行流程:

                                                

        Spring  AOP的基本概念:

1.  目标对象 : 自己写的类,想要增强的类。

2.  AOP代理啊 : 经过代理的类,实现增强。由AOP框架生成。

3.  AOP代理方法 :  Advice + 目标方法 + Advice.

4.  Advice :  增强处理。

5.  pointcut : 切入点。

      配置spring AOP的三个基本要素:

1.  在目标方法的哪里织入(before、after、after turn、after throwing、around)。

2.  通过execution表达式,指定对哪个类的哪个方法进行织入。

3.  指定织入的代码。

示例代码:

目标类:

public class UserService {
	
	private UserDao dao;

	public void test() {
System.out.println("test method run . . . ");
	}
	
	public void setDao(UserDao dao) {
System.out.println("setDao method run . . . ");
		this.dao = dao;
	}
	
	public long getUserTotal() {
System.out.println("getUserTotal method run . . . ");
		return 100;
	}

	public String getUserName(Integer id) {
System.out.println("getUserName method run . . . ");
		if(id <= 0) {
			throw new NullPointerException("id不可以小于0");
		}
		
		return "haha";
	}
	
}


before织入方法:

public class BeforeAdvice {
	
	public void check() {
		System.out.println("-------权限检查-------");
	}
	
	public void parameCheck(Integer arg) {
		System.out.println("--------权限检查,获得目标方法的参数:" + arg + "---------");
	}
}

before配置:

<bean id="before" class="spring.demo.aop.advice.BeforeAdvice"/>
	<aop:config>
			<!-- 对【无返回值,无形参】的方法进行织入-->
			<aop:pointcut id="widhoutR_withoutP" 
					expression="execution(void spring.demo.service.UserService.test())"/>
			
			<!-- 对【无返回值,有形参】的方法进行织入 -->
			<aop:pointcut id="widhoutR_P" 
					expression="execution(void spring.demo.service.UserService.setDao(spring.demo.dao.UserDao))" />
			
			<!-- 对【有返回值,无形参】的方法进行织入 -->
			<aop:pointcut id="R_widhoutP" 
					expression="execution(long spring.demo.service.UserService.getUserTotal())"/>
			<!-- 对【有返回值,有形参】的方法进行织入指定方法 -->
			<aop:pointcut id="R_P" 
					expression="execution(String spring.demo.service.UserService.getUserName(Integer)) and args(arg)"/>
			
		<aop:aspect ref="before">
			<aop:before method="check" pointcut-ref="widhoutR_withoutP"/>
			<aop:before method="check" pointcut-ref="widhoutR_P"/>
			<aop:before method="check" pointcut-ref="R_widhoutP"/>
			<aop:before method="parameCheck" pointcut-ref="R_P"/>
		</aop:aspect>
		
	</aop:config>


poincut配置的3个位置,其作用域也不同:

           1.   在<aop:config>中。

           2.   在<aop:aspect>中。

           3.   在<aop:before pointcut="...">

after织入方法:

public class AfterAdvice {
	
	public void loginfo() {
		System.out.println("-------日志记录--------\n");
	}
}
after织入配置:

<bean id="after" class="spring.demo.aop.advice.AfterAdvice"/>
	<aop:config>
		<!-- 对UserService类中的所有方法进行织入 -->
		<aop:pointcut id="after_exe"
			expression="execution(* spring.demo.service.UserService.*(..))"/>
			
		<aop:aspect ref="after">
			<aop:after method="loginfo" pointcut-ref="after_exe"/>
		</aop:aspect>
	</aop:config>

after throwing织入方法:
public class ExceptionAdvice {
	
	public void printNullPointerMessage(NullPointerException npe) {
		System.out.println("-------出空指针异常 : " + npe.getMessage() + "-------");
	}
	
	public void printMessage() {
		System.out.println("-------出异常-------");
	}
	
}
after throwing配置:

<aop:config>
		<aop:pointcut id="exception_exe" 
			expression="execution(* spring.demo.service.UserService.*(..))"/>
				
		<!--  对所有异常织入 -->
		<aop:aspect ref="exception">
			<aop:after-throwing method="printMessage" pointcut-ref="exception_exe"/>
		</aop:aspect>
		 
		<!-- 对指定的异常throwing织入 -->
		<aop:aspect ref="exception">
			<aop:after-throwing method="printNullPointerMessage" pointcut-ref="exception_exe" throwing="npe"/>
		</aop:aspect>
	</aop:config>

after returning织入方法:

public class ReturnAdvice {
	
	public void returning() {
		System.out.println("------对没有抛出异常,有返回值的方法织入---------");
	}
	
	//此方法的参数类型和目标方法的返回值类型要相同
	public void afterReturning(long userTotal) {
		System.out.println("------对没有抛出异常,返回值为long的方法织入---------");
	}
	
}

after returning配置:

<bean id="returning" class="spring.demo.aop.advice.ReturnAdvice"/>
	<aop:config>
		<aop:pointcut id="returning_exe"
			expression="execution(* spring.demo.service.UserService.*(..))"/>
		
		<aop:aspect ref="returning">
			<!-- 对所有返回值的方法织入 -->
			<aop:after-throwing method="returning" pointcut-ref="returning_exe"/>
			
			<!-- 对所有返回long类型的方法织入 -->
			<aop:after-returning method="afterReturning" pointcut-ref="returning_exe" returning="userTotal"/>
		</aop:aspect>
		
	</aop:config>

around织入方法:

public class AroundAdvice {
	@SuppressWarnings({ "null" })
	public Object advice(ProceedingJoinPoint pj) throws Throwable {
		System.out.println("目标方法的签名 : " + pj.getSignature());
		
		Object[] args  = pj.getArgs();
		//可以获得目标方法的参数,也可以对其进行处理
		System.out.println("目标方法的原参数 : " + Arrays.toString(args));
		args[0] = (Integer)args[0] + 100;
		
		Object result;
		//可以决定是否执行目标方法
		if(args == null && args.length == 0) {
			result = pj.proceed();
		} else {
			result = pj.proceed(args);
		}
		
		//也可以对目标方法的返回值进行修改,但是必须要和原方法的返回值类型一样
		result = (String)result + " world " + Arrays.toString(args);
		System.out.println("目标方法执行结束");
		
		return result;
	}
}

around配置:

<bean id="around" class="spring.demo.aop.advice.AroundAdvice"/>
	<aop:config>
	
		<aop:pointcut id="around_exe"
			expression="execution(* spring.demo.service.UserService.getUserName(..))"/>
		
		<aop:aspect ref="around">
			<aop:around method="advice" pointcut-ref="around_exe"/>
		</aop:aspect>
				
	</aop:config>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值