AOP(Aspect-Oriented Programming)面向切面编程

  1. AOP对OOP的补充,而不是替代
  2. OOP的核心单位是类,而AOP则是切面
  3. 典型的例子包括日志,验证,事务管理
  4. 优点(1)使开发人员集中关注于系统的核心业务逻辑 (2)更利于创建松散的,可复用的,可扩展的软件系统
    在这里插入图片描述切面:切点和通知
    在这里插入图片描述
    五种通知类型(增强类型)
    在这里插入图片描述1. 前置和后置指的是时间;
    2.最终通知相当于finally通知,都会执行

五种通知的接口:

(1)前置通知

public class BeforeAdvices implements MethodBeforeAdvice{
	
	@Override
	public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
		System.out.println("切面方法对象是"+arg0);
		System.out.println("切面方法参数列表是"+Arrays.asList(arg1));
		System.out.println("切面方法应用的对象是"+arg2);
		System.out.println("前置通知执行");
	}

(2)后置通知

public class AfterReturningsAdvice implements AfterReturningAdvice{
	@Override
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
		System.out.println("后置通知执行");
		System.out.println("执行结果是"+returnValue);//返回结果 
		
	}

(3)异常通知

public class ThrowAdvice implements ThrowsAdvice{
	
	//注意异常类型
	public void afterThrowing(Exception ex) throws Throwable {
       System.out.println("异常信息是"+ex.getMessage());
       System.out.println("异常通知执行");
    }

(4)最终通知

public class Afters implements AfterAdvice{
}

(5)环绕通知

public class Arounds implements MethodInterceptor{
//invoke调用 MethodInvocation.proceed得到一个Object对象
	@Override
	public Object invoke(MethodInvocation arg0) throws Throwable {
		System.out.println("前置通知执行中");
		Object proceed = arg0.proceed();
		System.out.println("环绕通知的结果"+proceed);
		System.out.println("后置通知执行中");
		return proceed;
	}

实现AOP的方法:(三种)

在这里插入图片描述

(1)使用Schema-based方式实现Aop

<!-- 使用Schema-based方式实现Aop -->
	<bean id="calculateImpl" class="com.xxx.schema.CalculateImpl"></bean>
	<!-- 实例化通知对象,把通知类注入到IOC容器中 ,在切面中引用 -->
	<bean id="before" class="com.xxx.schema.BeforeAdvices"></bean>
	<!-- 注意:最终通知实现类没有重写方法 -->
	<!-- <bean id="after" class="com.xxx.schema.Afters"></bean> -->
	<bean id="throw" class="com.xxx.schema.ThrowAdvice"></bean>
	<bean id="around" class="com.xxx.schema.Arounds"></bean>
	<bean id="afterreturn" class="com.xxx.schema.AfterReturningsAdvice"></bean>
	<!-- 配置AOP,把切面织入到目标对象 -->
	<aop:config>
		<!-- 配置切点,*是通配符,方法参数(..) -->
		<aop:pointcut expression="execution(public int com.xxx.schema.CalculateImpl.*(..))" id="point"/>
		<!-- 配置通知 -->
		<aop:advisor advice-ref="before" pointcut-ref="point"/>
		<!-- <aop:advisor advice-ref="after" pointcut-ref="point"/> -->
		<aop:advisor advice-ref="throw" pointcut-ref="point"/>
		<aop:advisor advice-ref="around" pointcut-ref="point"/>
		<aop:advisor advice-ref="afterreturn" pointcut-ref="point"/>
	</aop:config> 

配置切点表达式,语法

<aop:pointcut expression=“execution(public int com.xxx.schema.CalculateImpl.*(…))” >

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)
问号表示当前项可以有也可以没有,其中各项的语义如下:
1. modifiers-pattern:方法的可见性,如public,protected;
2. ret-type-pattern:方法的返回值类型,如int,void等;
3. declaring-type-pattern:方法所在类的全路径名,如com.spring.Aspect;
4. name-pattern:方法名类型,如buisinessService();
5. param-pattern:方法的参数类型,如java.lang.String;
6. throws-pattern:方法抛出的异常类型,如java.lang.Exception;

(2)AspectJ之XML文件方式实现AOP

public class MyAspect {
	//在Java文件中选择类名,然后Copy Qualified Name;
	//怎样访问当前连接点的细节
	public void one(JoinPoint jp){
		String name = jp.getSignature().getName();
		Object[] args = jp.getArgs();
		System.out.println(name+"前置通知执行"+",参数列表是"+Arrays.asList(args));
	}
	public void two(JoinPoint jp,Object re){
		
		String name = jp.getSignature().getName();
		System.out.println("后置通知执行的返回结果是"+re);
	}
	public void three(JoinPoint jp,Exception ex){
		System.out.println("异常通知执行的异常信息为"+ex);
	}
	public void four(){
		System.out.println("最终通知执行");
	}
	public Object five(ProceedingJoinPoint pjp){
		Object[] args = pjp.getArgs();
		String name = pjp.getSignature().getName();
		Object result=null;
		try {
			System.out.println(name+"环绕准备就绪,参数列表是:"+Arrays.asList(args));
			System.out.println("前置通知执行");
			result = pjp.proceed();
			System.out.println(name+"的返回结果是:"+result);
			System.out.println("后置通知执行");
		} catch (Throwable e) {
			
			e.printStackTrace();
			System.out.println("异常通知执行");
		}finally{
			System.out.println(name+"环绕执行完毕,参数列表是:"+Arrays.asList(args));
			System.out.println("最终通知执行");
		}
	
		return result;
		
	}
}

<bean id="calculateImpl" class="com.xxx.aspectj.xml.CalculateImpl"></bean>
 	<bean id="aspects" class="com.xxx.aspectj.xml.MyAspect" />
 	<!-- 配置切面 -->
 	<aop:config>
 		<aop:aspect id="aspect" ref="aspects">
 			<aop:pointcut expression="execution(* com.xxx.aspectj.xml.CalculateImpl.add(..)) " id="pointcut"/>
 			<aop:around method="five" pointcut-ref="pointcut" /> 
 			<!-- <aop:after-returning method="two"  pointcut-ref="pointcut"  returning="re"/>
 			<aop:before method="one" pointcut-ref="pointcut" />
 			<aop:after-throwing method="three" pointcut-ref="pointcut"  throwing="ex"/>
 			<aop:after method="four" pointcut-ref="pointcut"  /> -->
 			
 	   </aop:aspect>
 	</aop:config>

(3)AspectJ之注解方式实现AOP

@Component
@Aspect

//通过@Order(*)标注指定切面优先级,*整数数值越小,优先级越高
public class MyAspect {
	//定义切点
	@Pointcut("execution(* com.xxx.aspectj.annotation.CalculateImpl.*(..))")
	public void pointcut(){
		
	}
	@Before("pointcut()")
	public void beforeone(JoinPoint jp){
		String name = jp.getSignature().getName();
		Object[] args = jp.getArgs();
		System.out.println(name+"前置通知1执行"+",参数列表是"+Arrays.asList(args));
	}
	@Before("execution(* com.xxx.aspectj.annotation.CalculateImpl.*(..))")
	public void beforefive(JoinPoint jp){
		String name = jp.getSignature().getName();
		Object[] args = jp.getArgs();
		System.out.println(name+"前置通知2执行"+",参数列表是"+Arrays.asList(args));
	}
	@After("execution(public int com.xxx.aspectj.annotation.CalculateImpl.*(..))")
	public void four(){
		System.out.println("最终通知执行");
	}
	@AfterReturning(pointcut="execution(public int com.xxx.aspectj.annotation.CalculateImpl.*(..))",returning="re")
	public void two(JoinPoint jp,Object re){
		
		String name = jp.getSignature().getName();
		System.out.println(name+"后置通知执行的返回结果是"+re);
	}
	@AfterThrowing(pointcut="execution(public int com.xxx.aspectj.annotation.CalculateImpl.*(..))",throwing="ex")
	public void three(JoinPoint jp,Exception ex){
		System.out.println("异常通知执行的异常信息为"+ex);
	}
	
	@Around("execution(public int com.xxx.aspectj.annotation.CalculateImpl.*(..))")
	public Object five(ProceedingJoinPoint pjp){
		Object[] args = pjp.getArgs();
		String name = pjp.getSignature().getName();
		System.out.println(name+"环绕前置就绪,参数列表是:"+Arrays.asList(args));
		Object result=null;
		try {
			result = pjp.proceed();
			System.out.println(name+"的环绕返回结果是:"+result);
		} catch (Throwable e) {
			
			e.printStackTrace();
			System.out.println("异常通知执行");
		}finally{
			System.out.println(name+"环绕后置执行完毕,参数列表是:"+Arrays.asList(args));
		}		
		return result;	
	}
}

<!-- spring不自动寻找带注解的类,需要告诉哪些包中存在带注解的类 -->
 	<context:component-scan base-package="com.xxx.aspectj.annotation"></context:component-scan>
 	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

测试

	public static void main(String[] args) {
		//加载配置文件
		ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext2.xml");
		CalculateImpl cal=(CalculateImpl) ac.getBean("calculateImpl");
		System.out.println(cal.add(3, 3));

	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值