SpringAOP学习日志(一)

SpringAOP(面向切面)编程

SpringAOP是针对不同问题的OOP编程的简单补充,是Spring框架中的一个重要内容。用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理。

基本术语

1.通知(Advice):切面要完成的工作以及何时完成执行
2.连接点(Join Point):程序中需要动态织入代码的一个点
3.切点(Pointcut):会匹配通知所要织入的一个或多个连接点,解决了在哪些类和方法的连接点上执行通知的问题
4.切面(Aspect):通知和切点的结合
5.引入(Introduction):引入允许我们向现有的类添加新方法或属性,使程序具有动态性。
6.织入(Weaving):把切面应用到目标对象的过程。可以在编译期、类加载期、运行期进行织入。

通知(Advice)常见的几种类型

前置通知:需要实现MethodBeforeAdvice接口
后置通知:需要实现AfterReturningAdvice接口
环绕通知:需要实现MethodIntercept接口
异常通知:需要实现ThrowsAdvice接口

基于XML文件实现的AOP

设置通知(Advice)类,实现相应接口,重写方法。
注意:ThrowsAdvice接口是一个空接口,实现它不需要重写方法,但是异常通知的方法名必须时afterThrowing(参数类型为可能发生异常的类型)

public class LogAdvice implements MethodBeforeAdvice, 
					AfterReturningAdvice,ThrowsAdvice {
	//前置
	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		System.out.println("-----------------------------");
		System.out.println("[日志输出]:前置通知");
		System.out.println("[方法名称]:"+method.getName());
		System.out.println("[方法参数]:"+Arrays.toString(args));
		System.out.println("[目标对象]:"+method);
	}
	//后置
	@Override
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
		System.out.println("[日志输出]:后置通知");
		System.out.println("[返回结果]:"+returnValue);
		System.out.println("-----------------------------");
	}
	public void afterThrowing(Exception ex) {
		System.out.println("[异常处理]:警报,出现异常!请尽快处理");
	}
	public void afterThrowing(NullPointerException ex){
		System.out.println("[异常处理]:警报,出现空指针异常");
	}

}

创建XML文件,声明Bean,使用JDk的反射机制,生成Proxy代理对象(BeanNameAutoProxyCreator自动代理对象创建工厂)

<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
		<property name="interceptorNames">
			<list>
				<value>logAdviceBean</value>
				<value>performanceAdviceBean</value>
			</list>
		</property>
		<!-- 注入Target目标对象Bean的名称匹配规则 -->
		<property name="beanNames">
			<list>
				<value>*ServiceBean</value>
				<value>*DaoBean</value>
			</list>
		</property>
	</bean>

设置切点和切面,配置方法匹配规则

<!-- Pointcut切点:确定目标方法 -->
	<bean id="daoInsertMethodPointcut" 
	class="org.springframework.aop.support.NameMatchMethodPointcut">
		<!-- 查找所有以Insert结尾的方法为目标方法(切点) -->
		<property name="mappedName" value="*Insert"/>
	</bean>
	
	<!-- Advisor Advice + Pointcut -->
	<bean id="defaultLogAdvisorBean" 
	class="org.springframework.aop.support.DefaultPointcutAdvisor">
		<property name="pointcut" ref="daoInsertMethodPointcut" />
		<property name="advice" ref="logAdviceBean" />
	</bean>

并且在interceptorNames中注入切面

<property name="interceptorNames">
			<list>
				<!-- 注入Advisor -->
				<value>LogAdvisorBean</value>
			</list>
		</property>

使用XML实现纯POJO切面

POJO:简单Java对象,通知(Advice)类不用实现指定接口,可自由定义通知方法。
XML配置方式:

<!-- AOP配置 -->
	<aop:config>
		<!-- 公共切点,可匹配多个切面 -->
		<aop:pointcut expression="execution(* com.apesource.dao.*.*Insert(..))" id="daoInsertMethod"/>
		<!-- 配置切面1 -->
		<aop:aspect ref="logAdviceBean">
			<!-- 配置通知“类型” -->
			<!-- 前置通知:在pointcut查找到的目标方法执行前,自动执行通知类中的指定method -->
			<aop:before method="methodBefore" pointcut-ref="daoInsertMethod"/>
			<!-- 后置通知 -->
			<aop:after-returning method="methodAfter" pointcut-ref="daoInsertMethod"/>
		</aop:aspect>
		<!-- 配置切面2 -->
		<aop:aspect ref="adminAdviceBean">
			<!-- 环绕通知 -->
			<aop:around method="around" pointcut-ref="daoInsertMethod"/>
		</aop:aspect>
	</aop:config>

而在通知(Advice)类中,虽然不用实现特定接口,可自定义通知方法,但方法的参数必须是JoinPoint(org.aspectj.lang.JoinPoint)类型,用于连接目标方法和当前通知方法。

public class LogAdvice{
	// "自定义"前置通知方法
	public void methodBefore(JoinPoint joinpoint){
		System.out.println("[日志输出]:--------前置通知----------------");
	}
	//  "自定义"后置通知方法
	public void methodAfter(JoinPoint joinpoint){
		System.out.println("[日志输出]:--------后置通知----------------");
	}
}

而环绕通知传入的参数为ProceedingJoinPoint类型,该接口继承JoinPoint 接口,可以调用目标方法(joinPoint.proceed()方法)。

public class AdminAdvice {
	// "自定义"环绕通知方法
	public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
		System.out.println("[日志输出]:--------环绕通知开始----------------");
		System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
		Object resultVal = joinPoint.proceed();
		System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
		System.out.println("[日志输出]:--------环绕通知结束----------------");
		return resultVal;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值