spring学习(十四)————SpringAOP知识点总结

目录

 

SpringAOP的一点理解

SpringAOP的基本术语

通过注解使用springAOP

springAOP的引入


SpringAOP的一点理解

其实springaop就是一个拦截器,springaop通过代理模式实现方法的拦截

SpringAOP的基本术语

1、切面:拦截器类,其中会定义切点以及通知

2、通知:切面当中的方法,包括:

  1. 前置通知:在动态代理反射原先方法前调用的方法
  2. 后置通知:在动态代理反射完原有方法后调用的方法
  3. 返回通知:如果方法正常执行,在调用完后置通知后,就调用返回通知
  4. 异常通知:如果方法出现异常,在调用完后置通知后,就调用异常通知
  5. 环绕通知:可以决定是否调用目标方法,同时可以控制方法的返回对象(这个通知具有一些细节,接下来会进一步说明)

3、引入:往代理对象中添加新的方法,但是新的方法不会被拦截

4、切点:即定义需要拦截的方法的特征,可以通过正则表达式匹配,也可以通过类的全限定名

5、连接点:需要拦截的方法

6、织入:生成代理对象并将切面内容嵌入流程中,将切面内容嵌入到流程中是什么意思呢?例如现在定义了前置通知,那么代理对象在调用被代理对象的方法之前就会调用前置通知

通过注解使用springAOP

@Aspect:表明这个类是一个切面

@Before:前置通知

@After:后置通知

@AfterReturning:正常通知

@AfterThrowing:异常通知

@Pointcut:切点,切点匹配方法有如下几种方式:

下面举一个简单的例子,项目结构:

Roleinterface:

package com.springdemo3;

public interface Roleinterface {
     void print();
}

Roleimplement:

package com.springdemo3;

public class Roleimplement implements Roleinterface{

	
    //连接点
	public void print() {
		System.out.println("this is AOP");
	}
	
}

AOP(切面):

package com.springdemo3;

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;

@Aspect
public class AOP {
    
    //切点
	@Pointcut("target(com.springdemo3.Roleimplement)")
	public void print() {};
	
    //前置通知
	@Before("print()")
	public void beforeprint() {
		System.out.println("这是前置方法");
	}
	
    //后置通知
	@After("print()")
	public void afterprint() {
		System.out.println("这是后置方法");
	}
	
    //返回通知
	@AfterReturning("print()")
	public void afterreturning() {
		System.out.println("正常返回");
	}

    //异常通知	
	@AfterThrowing("print()")
	public void afterthrowing() {
		System.out.println("异常防护");
	}
	
}

configurations(配置类):

package com.springdemo3;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.Bean;

@Configuration
@EnableAspectJAutoProxy
public class configurations {

	
	@Bean
	public Roleimplement getRoleinplement() {
		return new Roleimplement();
	}
	
	@Bean
	public AOP getAOP() {
		return new AOP();
	}
	
}

App(启动类):

import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 *
 */
public class App 
{
    public static void main( String[] args )
    {
    	ApplicationContext ctx = new AnnotationConfigApplicationContext(configurations.class);
    	Roleinterface temp=(Roleinterface)ctx.getBean(Roleinterface.class);
    	temp.print();
    }
}

运行结果:

关于springAOP相应的内容都已经标记出,接下来我们看看环绕通知,在切面中添加函数,函数参数ProceedingJoinPoint可以调用proceed方法,该方法会调用连接点,同时调用前置通知:

	@Around(value = "print()")
	public void aroundfunc(ProceedingJoinPoint func) {
		System.out.println("执行环绕方法");
		try {
			func.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("环绕方法执行完毕");
	}

运行结果:

当切面中存在环绕通知时,在外部调用连接点方法,其实调用的是环绕通知,proceed方法允许环绕通知调用连接点方法,proceed方法将前置通知与连接点捆绑在一起,环绕通知就相当于连接点,根据环绕通知的执行结果,决定调用异常通知或是正常通知

springAOP的引入

我对springAOP引入的理解就是增强代理对象的功能,其实就是让代理对象继承某些接口(不能是类),内部应该是通过反射的方式调用接口实现类的方法,为什么只能引入接口的方法呢?这是java代理方式决定的,CGLIB代理已经继承被代理类了(java是单继承),JDK代理对象生成的时候只能传递接口

(JDK生成代理对象的方法为Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), this),看不到与类继承有关的参数)

使用引入,只需要在上述项目的基础上更改一下:

Userinterface:

package com.springdemo3;

public interface Userinterface {
     void print_sec();
}

Userimplement:

package com.springdemo3;

public class Userimplement implements Userinterface{

	public void print_sec() {
		System.out.println("这是引入");
		
	}

}

在AOP(切面)中添加:

//value表示引入应该应用于哪些被代理对象的代理对象
//defaultImpl表示接口的默认实现类是谁,引入的实现类会被注册为通知(advice)
@DeclareParents(value="com.springdemo3.Roleinterface+",defaultImpl=Userimplement.class)
Userinterface userinterface;

添加断点查看代理对象:

可以注意到引入被注册为了advice

当有多个通知应用于同一个连接点时,通知的执行顺序是不确定的,可以在切面类中使用@Order(优先级)来指定执行顺序,此时spring会将多个通知组织成责任链的模式

猜你喜欢

转载自blog.csdn.net/dhaiuda/article/details/82423344