spring_03AOP编程

AOP 编程

AOP( Aspect Oricented Programming ) 面向切面编程

是对所有对象或者是一类对象进行编程 

核心是(不  还)

	在不增加代码的基础上,还增加新的功能

spring AOP实现原理

  • 动态代理&CGLib代理

      spring能够为容器中管理的对象生成动态代理对象
    
      以前我们要使用动态代理,我们需要自己调用下面这个方法:
    
      	Proxy.newProxyInstance(xx,xx,xx)
    
      生成代理对象
    
    
      spring能帮我们生成代理对象
    
  • 动态代理和CGLib代理的区别:

      动态代理:被代理的对象必须实现接口,才能产生代理对象,
      	
      	如果没有接口将不能使用动态代理技术
    
      cglib代理:第三方代理技术,cglib代理,可以对任何类生成代理,代理的原理是
    
      	对目标对象进行继承代理。如果目标对象被final修饰,那么该类无法被
    
      	cglib代理
    
  • 具体的顺序:有接口的话,优先使用 动态代理,没有的话使用cglib代理

AOP的一些术语:

  1. Joinpoint(连接点):

     目标对象中,所有可以增强的方法
    
  2. Pointcut(切入点):

     目标对象,已经增强的方法
    
  3. Afvice(通知/增强):

     增强的代码
    
  4. Target(目标对象):

     被代理的对象
    
  5. Weaving(织入):

     动词,将通知织入连接点形成切入点
    
  6. Proxy(代理):

     将通知织入目标对象后,形成代理对象
    
  7. aspect(切面):

     切入点+通知
    

使用spring中的AOP:

  1. 导包

     (4+2+2+2)4个核心+2个日志
    
     +(2)spring的aop包:
    
     	spring-aop.jar 与 spring-aspects.jar
     
     +(2)spring需要第三方aop包:
    
     	com.springsource.org.aopalliance-1.0.0.jar
     	
     	com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
    
  2. 准备目标对象

     package org.spring.service;
    
     public class UserService {
    
     	public void save(){
     		System.out.println("保存用户");
     	}
     	public void delete(){
     		System.out.println("删除用户");
     	}
     	public void find(){
     		System.out.println("查询用户");
     	}
     	public void update(){
     		System.out.println("更新用户");
     	}
     }
    
  3. 定义通知:

     前置通知
    
     	目标方法运行之前调用
    
     后置通知(如果出现异常不会调用)
    
     	在目标方法运行之后调用
    
    
     环绕通知
    
     	在目标方法之前和之后都调用
    
     异常拦截通知
    
     	如果出现异常,就会调用
    
     后置通知(无论是否出现异常都会调用)
    
     	在目标运行之后调用
    
    
    
     特殊:环绕通知需要手动调用目标方法
    
    
     package org.spring.advice;
    
     import org.aspectj.lang.ProceedingJoinPoint;
    
     public class MyAdvice {
     	//前置通知
     	public void before(){
     		System.out.println("前置通知");
     	}
     	//后置通知
     	public void afterRunning(){
     		System.out.println("后置通知(如果出现异常不会调用)");
     	}
     	//环绕通知
     	public Object around(ProceedingJoinPoint  pjp) throws Throwable{
     		System.out.println("环绕通知-前");
     		Object procced = pjp.proceed();
     		System.out.println("环绕通知-后");
     		return procced;
     	}
     	//异常通知
     	public void afterException(){
     		System.out.println("异常通知");
     	}
     	//后置通知
     	public void after(){
     		System.out.println("后置通知(出现异常也会调用)");
     	}
     }
    
  4. 配置进行织入,将通知织入目标对象中

     <!-- 准备工作:导入aop(约束)命名空间 -->
     <!-- 1.配置目标对象 -->
     	<bean name="userService" class="org.spring.service.UserService"></bean>
     <!-- 2.配置通知对象 -->
     	<bean name="myAdvice" class="org.spring.advice.MyAdvice"></bean>
     <!-- 3.配置将通知织入目标对象 -->
     	<aop:config>
     		<!-- 配置切入点
     			public void org.spring.service.UserService.save()
     			void org.spring.service.UserService.save()
     			* org.spring.service.UserService.save()
     			* org.spring.service.UserService.*()
     			* org.spring.service.UserService.*(..)
     			* org.spring.service.*Service.*(..)
     			* org.spring.service..*Service.*(..)
     		 -->
     		<aop:pointcut expression="execution(* org.spring.service.*Service.*(..))" id="pc"/>
     		<!-- 通知对象 -->
     		<aop:aspect ref="myAdvice">
     			<!-- 指定通知类型与通知方法名以及切入点 -->
     			<aop:before method="before" pointcut-ref="pc"/>
     			<aop:after-returning method="afterRunning" pointcut-ref="pc"/>
     			<aop:around method="around" pointcut-ref="pc"/>
     			<aop:after-throwing method="afterException" pointcut-ref="pc"/>
     			<aop:after method="after" pointcut-ref="pc"/>
     		</aop:aspect>
     	</aop:config>
    

springAOP的注解配置

  1. applicationContext.xml中的配置

     <context:component-scan base-package="org.spring"></context:component-scan>
     <!--开启切面自动代理-->
     <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
  2. 通知中的注解:

     package org.spring.advice;
    
     import org.aspectj.lang.ProceedingJoinPoint;
     import org.aspectj.lang.annotation.After;
     import org.aspectj.lang.annotation.AfterReturning;
     import org.aspectj.lang.annotation.AfterThrowing;
     import org.aspectj.lang.annotation.Around;
     import org.aspectj.lang.annotation.Aspect;
     import org.aspectj.lang.annotation.Before;
     import org.aspectj.lang.annotation.Pointcut;
     import org.springframework.stereotype.Component;
     @Component("myAdvice")
     //表示该类是一个通知类
     @Aspect
     public class MyAdvice {
     	//表示切入点的方法
     	@Pointcut("execution(* org.spring.service.*Service.*(..))")
     	public void pc(){}
    
     	//前置通知
     	@Before("MyAdvice.pc()")
     	public void before(){
     		System.out.println("前置通知");
     	}
     	//后置通知
     	@AfterReturning("MyAdvice.pc()")
     	public void afterRunning(){
     		System.out.println("后置通知(如果出现异常不会调用)");
     	}
     	//环绕通知
     	@Around("MyAdvice.pc()")
     	public Object around(ProceedingJoinPoint  pjp) throws Throwable{
     		System.out.println("环绕通知-前");
     		Object procced = pjp.proceed();
     		System.out.println("环绕通知-后");
     		return procced;
     	}
     	//异常通知
     	@AfterThrowing("MyAdvice.pc()")
     	public void afterException(){
     		System.out.println("异常通知");
     	}
     	//后置通知
     	@After("MyAdvice.pc()")
     	public void after(){
     		System.out.println("后置通知(出现异常也会调用)");
     	}
     }
    
posted @ 2018-01-15 21:46  厨房有只偷吃的猫  阅读(305)  评论(0编辑  收藏  举报