2.spring与AOP

1. AOP
1. AOP概念:面向切面编程。底层通过封装动态代理技术实现。
2.动态代理:在不修改源码的情况下,实现了方法的增强。
3.使用AOP技术,关注2点:
  1).手动创建增强方法; 2).通过配置文件,告诉spring在哪些方法上使用增强方法。
1.1 动态代理
AOP面向切面编程的底层实现,AOP封装两种动态代理:

(1) proxy的动态代理(基于接口,jdk提供)
	AccountService accountService = new AccountServiceImpl();
	//使用JDK的Proxy类,创建代理增强类
	AccountService proxy = (AccountService)Proxy.newProxyInstance(
        //参数一:和目标对象一样的类加载器
    	accountService.getClass().getClassLoader(),
        //参数二:和目标对象一样的接口--数组
        new Class[] {accountService.getClass()},
        //参数三:实现Invocationhandler接口的增强类(外部类、内部类、lambada实现)     
        new Invocationhandler( 
            	// 参数一:proxy 一般不要用,为代码自己调用的代理对象。
                 public Object invoke(Proxy proxy,Method method,object[] args){
                     if("add".equals(method.getName())){
                         try(流对象){
                             //1.方法执行前增强
                             method.invoke(accountService,args);//执行原方法
                             //2.方法执行后增强 
                         }catch{
                             //3.异常增强
                         }finally{
                             //最终增强 
                         }            
                     }else{
                         method.invoke(accountService,args);//执行原方法
                     }
                     //返回原方法执行后的返回值;或者返回加工后的返回值. 
                     return null; 
                 } 	
             )
       );
    proxy.add();  // proxy可以接受调用后的返回值。

(2) Enhancer的动态代理(基于父类 cglib提供)
    1.导入Cglib的包; 2.目标类不能被final关键字修饰
    AccountService accountService = new AccountServiceImpl();
	//Cglib的工具类Enhancer,创建代理增强类
    AccountService proxy = (AccountService)Enhancer.create(
    	//参数一:目标类的字节码文件
    	accountService.getClass(),
    	//参数二:增强类
    	new MethodInterceptor(
      	//参数三:methodProxy 用不到,方法的代理对象,内部自己调用
   		public object intercept(
            Object Proxy,Method method,object[] arg,MethodProxy methodProxy){
             if("add".equals(method.getName())){
                 try(流对象){
                     //1.方法执行前增强
                     method.invoke(accountService,args);//执行原方法
                     //2.方法执行后增强 
                 }catch{
                     //3.异常增强
                 }finally{
                     //4.最终增强 
                 }            
             }else{
                 method.invoke(accountService,args); //执行原方法
             }
          	return null; 
      } 
  );
  enhancer.add();

  基于接口的Proxy动态代理,与目标类是兄弟关系;
  基于父类的Enhancer动态代理,与目标类是父子关系,目标类为父类;
2. 基于全XML的AOP配置
实现步骤:
1.创建Maven工程,导入坐标。(IOC容器坐标、AOP坐标)
2.创建创建增强类,创建增强方法。创建被增强类,被增强方法。(不加注解,全XML的bean配置)               
3.创建spring配置文件:配置通知、切入点。

  // 1.配置被增强类
  <bean id="AccountService" class="cn.itcast.service.impl.AccountServiceImpl">
  // 2.配置增强类
  <bean id="logger" class="cn.itcast.untils.Logger">
  // 3.AOP配置实现
  <aop:config>
  	<aop:pointcut id="pt" expresition="excution( * cn.itcast..save(..))"/> 
  	<aop:aspect ref="logger"> 
  		//前置通知
  	 	<aop:before method="before" pointcut-ref="pt"></aop:before>
  	 	//后置通知
  	 	<aop:after-returning method="afterReturning" pointcut-ref="pt"></aop:after-returning>
  	 	//异常通知
  	 	<aop:after-throwing method="afterThrowing" pointcut-ref="pt"></aop:after-throwing>
  	 	//最终通知
  	 	<aop:after method="after" pointcut-ref="pt"></aop:after>
  	 	//注意: 最终通知和后置通知,是按照配置的上下顺序执行的,想要固定顺序,可使用环绕通知。
  	 	//      环绕通知不能跟上边通知一起使用,环绕通知固定执行顺序。
  	 	//环绕通知
  	 	<aop:around method="around" pointcut-ref="pt"></aop:around>
     </aop:aspect>
  </aop:config>

环绕通知的增强方法:
    public void around(ProceedingJoinPoint joinPoint){
        try {
            // 前置
            System.out.println("前置通知(之前增强)");
            // 原方法调用
            joinPoint.proceed(); //inboke
            // 后置
            System.out.println("后置通知(之后增强)");
        }catch (Throwable throwable){
            // 异常
            System.out.println("异常通知(异常增强)");
        }finally {
            // 最终
            System.out.println("最终通知(最终增强)");
        }
    }
      
      
表达式语法:excution( * cn.itcast..AccountImpl.save(..))
      最前边的*: 代表任意的返回值,public 省略没写。
      .. 可以代替包名,代表任意包以及其子包
      .. 可以代表参数,代表任意参数
      *  可以代表包,代表任意包;可以代表类,任意类;代表方法名,任意方法名。
3. 基于半XML半注解的AOP配置
实现步骤:
1.创建Maven工程,导入坐标。(IOC容器坐标、AOP坐标)
2.创建增强类,创建增强方法。创建被增强类,被增强方法。(加注解,添加注解扫描context:component实现) 
3.创建spring配置文件,配置IOC容器扫描,AOP开启注解。
<context:component-scan base-package="cn.itcast"></context:component-scan >
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>  //开启aop注解。
    
切面类注解(增强类):
类上:@Component(“id”) @Ascept

切面类方法上:
//抽取切入点表达式:1.创建一个无参数、无返回值的方法;2.使用@Pointcut("表达式");3增强方法调用抽取方法。
@pointcut("execution(* cn.itcast..save(..))")
Public void pointcut(){} 
@Before("pointcut()")  //前置通知 
@After-returning("pointcut()") //后置通知
@After-throwing("pointcut()")  //异常通知
@after("pointcut()")  //最终通知

@Around("pointcut()") //环绕通知
               
4. 基于纯注解的AOP配置
实现步骤:
与3实现步骤几乎相同,只是想spring配置文件,换做配置类即可。测试的时候,加载配置类。

3.创建配置类SpringConfig类,添加注解实现配置文件中,以下配置。
<context:component-scan base-package="cn.itcast"></context:component-scan >
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>  //开启aop注解使用
@Configuration //实现配置类
@ComponentScan //实现注解扫描
@EnableAspectJAutoProxy //开启AOP注解使用    
public class SpringConfig{}  

测试时,注解修改:
@Runwith(SpringJunit4ClassRunner.calss)
@ContextConfigration(classes=SpringConfig.class)
//@ContextConfigration(locations="classpath:application.xml")    
public class SpringJunit{ }
4.AOP专业术语–面试题
目标对象--Target:   要增强的对象
代理对象--Proxy :   增强后的代理对象
连接点--Joinpoint:  目标对象的所有方法
切入点--Pointcut:   目标对象中要被增强的方法(在增强类中配置)
通知--Advice:       自己写的增强方法

前置通知:在目标方法之前进行的增强方法
后置通知:在目标方法之后进行的增强方法
异常通知:在目标方法异常之时的增强方法
最终通知:在目标方法增强之后,一定会执行的方法

环绕通知:能够代替上面4Aspect(切面):  切入点+通知=切面 --> 被增强方法+增强方法==切面
Weaving(织入): 将切入点集成到切面的这一个过程,我们称为织入 -->目标方法+增强方法的合成过程==织入过程
引用\[1\]中提到的错误是关于Spring AOP的切点配置路径有误导致的。解决方法是将原配置中的`execution(* com.kang.service.(…))`修改为`execution( com.kang.service.ServiceImpl.(…))`。这样可以正确匹配到切点。\[1\] 引用\[2\]中提到的解决方法是导入了`org.aspectj.aspectjweaver`的依赖,版本为`1.8.14`。这个依赖可能是解决问题的关键。\[2\] 引用\[3\]中提到的错误可能是由于Spring AOP代理混用导致的。解决方法是在XML配置文件中添加`<aop:aspectj-autoproxy proxy-target-class="true"/>`来解决这个问题。\[3\] 综上所述,如果在`com.spring.aop.aspectj`下不成功,可能是由于切点配置路径有误、缺少依赖或者代理混用等原因导致的。你可以根据上述提到的解决方法来尝试解决这个问题。 #### 引用[.reference_title] - *1* [Error creating bean with name ‘org.springframework.aop.aspectj.AspectJPointcutAdvisor#0](https://blog.csdn.net/quest101/article/details/117877362)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [spring AOP 错误 org.springframework.aop.aspectj.AspectJPointcutAdvisor 等等](https://blog.csdn.net/weixin_30278237/article/details/97573038)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Failed to instantiate [org.springframework.aop.aspectj.AspectJExpressionPointcut]: No default constr](https://blog.csdn.net/thetimelyrain/article/details/96509488)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值