springboot中使用 AOP

***springAOP使用代理模式实现,代理模式可以将我们的业务代码,和扩展功能进行分 离,由代理对象去做扩展的方法,业务代码无需做很大的改动,springAOP就是对代理模式的一种实现,在调用目标方法对象之前由代理对象去做一些别的功能

动态代理例子
java.lang.reflect反射包下,Proxy.newProxyInstance()静态方法可以创建代理对象
以及InvocationHandler 代理实例的调用处理程序 实现的接口可以查看api学习

package com.springboot.proxyFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.springframework.beans.factory.annotation.Autowired;
import com.springboot.mapp.Ainmal;
import com.springboot.mapp.Cat;
//代理工厂
//@Component
public class ProxyFactory {
	// 目标对象
	@Autowired
	private Cat cat;//Cat实现了Ainmal接口

	public ProxyFactory(Cat cat) {
		this.cat=cat;
	}
	//创建代理对象
	@SuppressWarnings("unchecked")
	public Ainmal getProxyObject(CarAdd carAdd) {//传入需要扩展功能的类,在调用目标方法之前或之后进行扩展
	//
	return (Ainmal)Proxy.newProxyInstance(
			//目标对象的类加载器
			cat.getClass().getClassLoader(),
			//目标对象实现的接口数组,程序会在运行时生成代理类,代理类会实现给定的接口
			cat.getClass().getInterfaces(),
			//代理对象需要调用的处理器,代理对象调用方法,都由处理器的invoke方法处理,调用目标对象中的方法
				new InvocationHandler() {
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						//carAdd.before();扩展方法
						Object rest=method.invoke(cat, args);
						//carAdd.after();扩展方法
						return rest;
					}
				});
					
	}
}

AOP核心概念

2、切面(aspect)

类是对物体特征的抽象,切面就是对横切关注点的抽象

3、连接点(joinpoint)

被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器

4、切入点(pointcut)

对连接点进行拦截的定义。execution(* com.springboot.controller.*.*(..))"你要拦截哪里的方法。。。

5、通知(advice)

所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类

6、目标对象

代理的目标对象

7、织入(weave)

将切面应用到目标对象并导致代理对象创建的过程

8、引入(introduction)

在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段

POM文件中引入依赖

	<dependency>
   		<groupId>org.springframework.boot</groupId>
   		<artifactId>spring-boot-starter-aop</artifactId>
   </dependency>
   <dependency>
   		<groupId>org.aspectj</groupId>
   		<artifactId>aspectjweaver</artifactId>
	</dependency>

切面类

package com.springboot.proxyFactory;
import java.lang.reflect.Modifier;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Component
@Aspect//切面
public class CarAdd {
	/**
	切点表达式:包下的所有类中的所有方法都会生成代理类,..表示任意参数。
	springAOP,在程序运行过程中,如果运行到切点匹配的(表达式时),
	jvm会动态的生成代理类,如果拦截到的类有实现接口,那么使用jdk动态代理,
	否则使用cglbi子类继承的方式进行生成代理类,类为finli不能被代理会报错,
	目标方法为静态,或者finli类型,aop的扩展功能不会被执行
	*/
	@Pointcut("execution(* com.springboot.controller.*.*(..))")
	public void qieDian() {}
	//前置通知
	//JoinPoint:封装了切点表达式中,匹配到的方法信息
	@Before("qieDian()")
	public  void before(JoinPoint joinPoint) {
		System.out.println(joinPoint);
		System.out.println("获取目标方法的方法名"+joinPoint.getSignature().getName());
		System.out.println("目标方法所属类的简单类名:"+joinPoint.getSignature().getDeclaringType().getSimpleName());
        System.out.println("目标方法所属类的类名:" + joinPoint.getSignature().getDeclaringTypeName());
        System.out.println("目标方法声明类型:" + Modifier.toString(joinPoint.getSignature().getModifiers()));
        System.out.println("获取被代理的对象"+joinPoint.getTarget());
        System.out.println("获取代理对象"+joinPoint.getThis())//获取request对象
        ServletRequestAttributes sqa=(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request=  sqa.getRequest();
        String requestURI = request.getRequestURI();
        String remoteAddr = request.getRemoteAddr(); 
        String requestMethod = request.getMethod();
        String declaringTypeName = joinPoint.getSignature().getDeclaringTypeName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
      	System.out.println("请求url=" + requestURI + ",客户端ip=" + remoteAddr + ",请求方式=" + 	requestMethod + ",请求的类名=" + declaringTypeName + ",方法名=" + methodName + ",入参=" + args);
      	System.out.println("猫吃饭之前");
	}
}

你可能感兴趣的:(springAOP学习,springboot,AOP)