Spring(四)AOP

AOP

AOP即为面向方面编程。

一个普通的类 -> 有特定功能的类
a.继承类 b.实现接口 c.注解 d.配置

注解、schema:JoinPoint
接口:Method method, Object[] args, Object target

都要将类放入容器中:xml放或注解扫描

首先导入jar包
aopaliance.jar
aspectjweaver.jar

(一)基于接口

1、前置(后置)

(1)编写类及方法

//实现MethodBeforeAdvice接口,普通类->前置通知֪
public class LogBefore  implements MethodBeforeAdvice{
	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		System.out.println("前置通知 ");							         		     		 System.out.println("目标对象"+target+",方法名"+method.getName()+",方法参数个				数"+args.length+"方法返回值"+returnValue);
	}
}

(2)配置xml

在这里插入图片描述

	<!-- 配置前置通知 -->

	<!-- 1、将方法放入容器 -->
	<!-- addStudent()所在方法 -->
	<bean id="studentService" class="org.lanqiao.service.impl.StudentServiceImpl">
		<property name="studentDao" ref="studentDao"></property>
	</bean>
	<!-- “前置通知”类 -->
	<bean id="logBefore" class="org.lanqiao.aop.LogBefore">
	</bean>

	<!-- 2、将addStudent()和通知进行关联 -->
	<aop:config>
		<!-- 事务类配置切入点(业务类方法) ,注意方法名的写法!!!参数写详细类型-->
		<aop:pointcut expression=
"execution(
 public void org.lanqiao.service.impl.StudentServiceImpl.deleteStudentByNo(org.lanqiao.entity.Student)
 )  
 or
execution(
 public * org.lanqiao.service.impl.StudentServiceImpl.addStudent(..)
 )"   
 id="poioncut"/>
		<!--将二者连接起来  advisor:相当于链接切入点和切面的线  advice-ref:前置方法ID-->	 
		<aop:advisor advice-ref="logBefore" pointcut-ref="poioncut"/>
	</aop:config>

在这里插入图片描述

2、异常通知

(1)编写类及方法

异常通知的实现类必须编写该方法:
public void afterThrowing([Method, args, target], ThrowableSubclass)即

a.public void afterThrowing(Method, args, target, ThrowableSubclass)或
b.public void afterThrowing( ThrowableSubclass)
public class LogException implements ThrowsAdvice {
    //必须为public
	public void afterThrowing(Method method, Object[] args ,Object target, Exception ex)
	{
		System.out.println("目标对象"+target+",方法名"+method.getName()+",方法参数个				数"+args.length+"异常类型"+ex.getMessage());
	}
}

(2)xml配置相似

3、环绕通知

在目标方法的前后、异常发生时、最终等各个地方都可以进行的通知,最强大的一个通知;
可以获取目标方法的全部控制权(目标方法是否执行、执行之前、执行之后、参数、返回值等)

在使用环绕通知时,目标方法的一切信息 都可以通过invocation参数获取到。

环绕通知底层是通过拦截器实现的。

(1)编写类及方法

public class LogAround  implements MethodInterceptor{

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		Object result  = null ;
		//前置通知
		try {	
			//中间,控制目标方法的执行,没有这句话则实际操作不会进行
			Object result  = invocation.proceed() ;
            //后置通知	 
System.out.println("目标对象"+invocation.getThis()+"方法		名,"+invocation.getMethod().getName()+",方法参数个数"+invocation.getArguments().length+"返回值,"+result);			
		}catch(Exception e) {
            //异常通知
		}	
		return result;
	}

}

(2)xml配置相似

(二)基于注解

先导入jar包,与实现接口的方式相同。

(1)xml配置

	<!-- 开启注解对AOP的支持 -->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
	<!-- 配置新包的扫描器 -->
	<context:component-scan base-package="org.lanqiao.aop">
	</context:component-scan>

扫描器会将指定的包中的@Componet @Service @Respository @Controller修饰的类产生的对象增加到IOC容器

(2)编写类及方法

org/lanqiao/aop/LogAspectAnnotation.java

//将通知类纳入容器,相当于在xml配置<bean id="logAnnotation" class="org.lanqiao.aop.LogAspectAnnotation">
@Component("logAnnotation")
@Aspect //声明此类是一个通知֪
public class LogAspectAnnotation  {
	
	//前置通知֪
	@Before("execution(public * addStudent(..))") //定义切点
	public void myBefore(JoinPoint jp) {
		System.out.println("目标对象"+jp.getTarget()+",方法名"+jp.getSignature().getName() +"参数列表"+Arrays.toString(jp.getArgs())+",参数个数"+ jp.getArgs().length  );
	}
    
	//后置通知֪
	@AfterReturning( pointcut= "execution(public * addStudent(..))" ,returning="returningValue" ) //声明返回值
	public void myAfter(JoinPoint jp,Object returningValue) {
		System.out.println("返回值"+returningValue );
	}
	
	//环绕通知
	@Around("execution(public * addStudent(..))")
	public void myAround(ProceedingJoinPoint jp  ) {
		//前置通知֪
		System.out.println("这里是前置通知");
		try {
			//中间
			jp.proceed() ;
			//后置通知֪
			System.out.println("这里是后置通知");
		}catch(Throwable e) {
			//异常通知֪
			System.out.println("这里是异常通知");
		}finally {
			//最终通知֪
			System.out.println("这里是最终通知");
		}
	}
	
	//异常通知
	@AfterThrowing(pointcut="execution(public * addStudent(..))",throwing="e")//声明异常为e
	//指定只会捕获空指针异常
	public void myException(JoinPoint pj, NullPointerException e) {
		System.out.println("异常为"+e.getMessage());
	}
	
	//最终通知֪
	@After("execution(public * addStudent(..))")
	public void myAfter() {
		System.out.println("666");
	}
	
	
}

注意后置通知返回值及异常通知的异常需声明

(三)基于Schema配置

a.编写一个普通类

有一些与注解相似

public class LogSchema  {
	
	//前置通知֪
	public void myBefore(JoinPoint jp) {
		System.out.println("目标对象"+jp.getTarget()+",方法名"+jp.getSignature().getName() +"参数列表"+Arrays.toString(jp.getArgs())+",参数个数"+ jp.getArgs().length  );
	}
    
	//后置通知֪,returning="returningValue" ) //声明返回值
	public void myAfter(JoinPoint jp,Object returningValue) {
		System.out.println("返回值"+returningValue );
	}
	
	//环绕通知
	public void myAround(ProceedingJoinPoint jp  ) {
		//前置通知֪
		System.out.println("这里是前置通知");
        Object result = null ;
		try {
			//中间
			result=jp.proceed() ;
			//后置通知֪
			System.out.println("这里是后置通知");
		}catch(Throwable e) {
			//异常通知֪
			System.out.println("这里是异常通知");
		}finally {
			//最终通知֪
			System.out.println("这里是最终通知");
		}
        return result;
	}
	
	//异常通知
	//指定只会捕获空指针异常
	public void myException(JoinPoint pj, NullPointerException e) {
		System.out.println("异常为"+e.getMessage());
	}
}

b.将该类通过配置,转为一个“通知”

    <!-- 将准备转为通知的类纳入ioc容器 -->
	<bean id="logSchema" class="org.lanqiao.aop.LogSchema"></bean>
	<!-- addStudent()所在方法 -->
	<bean id="studentService" class="org.lanqiao.service.impl.StudentServiceImpl">
		<property name="studentDao" ref="studentDao"></property>
	</bean>

	<aop:config>
		<!-- 切入点(连接线的一端:业务类的具体方法) -->
		<aop:pointcut expression="execution(public * org.lanqiao.service.impl.StudentServiceImpl.addStudent(..))"   id="pcShema"/>		
        
		 <!-- schema方式连接线连接-->
		 <aop:aspect ref="logSchema">	 
		  	<!-- 前置 -->
		 	<aop:before method="before" pointcut-ref="pcShema"/>
		 	<!-- 后置,有返回值需声明-->
		 	<aop:after-returning method="afterReturning" returning="returnValue" pointcut-ref="pcShema"/>
            <!-- 异常,有异常需声明 -->
		 	<aop:after-throwing method="whenException" pointcut-ref="pcShema" throwing="e"/>
		 	<!-- 环绕,有返回值???声明吗?-->
		 	<aop:around method="around" pointcut-ref="pcShema" />	
		 </aop:aspect>	 	
	</aop:config>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值