AOP原理以及Springboot直接使用

AOP原理以及Springboot直接使用

实例模板

@Component
@Aspect
public class Aoplog {


    @Pointcut("execution(* com.joint.cert.controller.*.*(..))") //controller下的所有的方法
    public void pointcut(){
    }
    
    //前置通知
    @Before("pointcut()")
    public void BerforeAdvice(JoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        System.out.println("准备执行"+signature.getName()+"方法");
        Object[] args = joinPoint.getArgs();
        System.out.println("获得方法参数信息"+ Arrays.asList(args));
    }

    //最终通知
    @After("pointcut()")
    public void AfterAdvice(JoinPoint joinPoint){
        System.out.println("----------------------"+joinPoint.getSignature().getName()+"方法执行完毕-----------------");
    }
    //如果参数中的第一个参数为JoinPoint,则第二个参数为返回值的信息
    //如果参数中的第一个参数不为JoinPoint,则第一个参数为returning中对应的参数
    //returning 只有目标方法返回值与通知方法相应参数类型时才能执行后置返回通知,否则不执行
    //后置通知
    
    @AfterReturning(value = "execution(* com.joint.cert.controller.*.*(..))",returning ="keys")
    public void AfterAdviceRuning(JoinPoint joinPoint,Object keys){
        System.out.println("--------------后置通知------------");
        System.out.println("------后置通知返回值"+keys);
    }
    
    //后置异常通知当抛出的异常和规定的异常相同时执行
    @AfterThrowing(value = "pointcut()",throwing = "exception")
    public void AfterThrowingAdvice(JoinPoint joinPoint,Exception exception){
        System.out.println("-----------后置异常通知---------------");
        System.out.println("错误"+exception);
    }
    
    //环绕通知:可以规定方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值
    @Around("execution(* com.joint.cert.controller.*.*(..))")
    public Object AroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
        System.out.println("---------------环绕通知-------------");
        System.out.println("----------环绕通知方法"+proceedingJoinPoint.getSignature().getName()+"---------------");
        try {
            Object proceed = proceedingJoinPoint.proceed();
            return proceed;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }finally {
            System.out.println("---------- 环绕通知结束 -------------");
        }
        return null;
    }
}

简单理解

AOP主要是为了在对象执行前后完成一些额外的逻辑,这时候就需要使用这个对象的代理对象来执行test的方法,然后就会执行AOP的前置方法中的业务逻辑,执行完毕后,根据反射的原理使用method.invoke(target,args)再去执行原对象的test方法

	@Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        //AOP的实现
        Object object = Proxy.newProxyInstance(
            bean.getClass().getClassLoader(),
            bean.getClass().getInterfaces(),
            new InvocationHandler() {//通过反射拿到类,拿到类加载器,拿到实现的接口,再写代理逻辑
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("代理逻辑");//执行的是代理逻辑
                method.invoke(bean,args); //TODO 执行的是bean当中的方法,也就是定义好的业务方法,					传进来的bean当中的,args就是参数
                //TODO 然后可以将对象返回,来一个狸猫换太子,过程已经执行了但是对象却不是原来的
                return null;
            }
        });
        return
           InstantiationAwareBeanPostProcessor.
            super.postProcessAfterInitialization(bean, beanName);
    }

这样的一套操作就在方法执行前执行了一套业务逻辑,使用代理对象

涉及到的类

核心AbstractAutoProxyCreator类
	//出现了循环依赖,执行lambda表达式执行这个方法
	@Override
	public Object getEarlyBeanReference(Object bean, String beanName) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName); // beanname aservice
        //把这个提前进行AOP的原始对象以及beanname等存进去
		this.earlyProxyReferences.put(cacheKey, bean);
		return wrapIfNecessary(bean, beanName, cacheKey);  //代理对象
	}
	//正常第四步进行AOP的地方
	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
            //这个map存的是那些提前进行了AOP的bean,在上边方法中
            //null!=bean
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                //没有提前进行过AOP,是正常的,在此处进行AOP
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}
//如有必要,包装给定的 bean,即如果它有资格被代理
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    //在当前targetSourcedBeans中存在的bean,表示在实例化之前就存在了对象
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
    //当前这个bean不用被代理
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
    //先判断当前bean需不需要AOP,比如当前bean的类型是pointcut,Advice,Advisor等就不需要AOP
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}
		// Create proxy if we have advice.
    	//获取当前beanclass所匹配的advisors?,判断有没有切面
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    	//如果匹配的不等于null,那么则进行代理,并返回代理对象
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
            //基于bean对象和Advisor创建代理对象
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            //存一个代理对象
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值