Go最全一篇文章了解如何实现方法增强(AOP方案)_aop增强多个接口,2024年最新Golang面试复习重点

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

@Override
public int selling(Long id) {
    target.selling(id);
    return SUCCESS;
}

}


静态代理测试类及结果如下,可以看到静态代理每次使用都需要写代理类,被代理类实例化后通过代理类的构造方法传入,再通过代理类进行调用代理方法。


![](https://img-blog.csdnimg.cn/20210925144801218.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5Zub6Zeu5Zub5LiN55-l,size_20,color_FFFFFF,t_70,g_se,x_16)



## 动态代理(Dynamic Proxy)


### JDK(Java Development Kit)动态代理


JDK动态代理通过Proxy类的newProxyInstance方法创建代理实例。



package com.hust.zhang.example;

import java.lang.reflect.Proxy;
import java.util.Objects;

public class JdkDynamicProxy {
private static final String PURCHASE = “purchasing”;
private static final String SELL = “selling”;

public static void main(String[] args) {
    SuperMarket market = new SuperMarketImpl();

    SuperMarket proxyInstance = (SuperMarket) Proxy.newProxyInstance(market.getClass().getClassLoader(), market.getClass().getInterfaces(), ((object, method, param) -> {
        int result = 0;
        if (Objects.equals(method.getName(), PURCHASE)) {
            System.out.println("代理商完成采购");
            result = (int) method.invoke(market, param);
        } else if (Objects.equals(method.getName(), SELL)) {
            System.out.println("代理商完成售卖");
            result = (int) method.invoke(market, param);
        }
        return result;
    }));

    proxyInstance.selling(1L);
}

}


上面的方式属于JDK动态代理,主要流程如下:


1. 创建代理对象,通过反射获取相同的接口,校验权限。
2. 重新生成一个类,实现被代理类所有接口。
3. 动态生成Java代码,添加进新的业务逻辑。
4. 编译新生成Java代码,重新加载到JVM中。


### CGLIB(Code Generation Library)动态代理


Cglib动态代理使用Enhancer类对方法进行增强。Enhancer类是一个增强类,它会生成动态子类以启动方法拦截。通过Enhancer.create()方法创建实例。



public class CglibDynamicProxy {
private static final String PURCHASE = “purchasing”;
private static final String SELL = “selling”;

public static void main(String[] args) {
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(SuperMarketImpl.class);

    enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
        int result = 0;
        if (Objects.equals(method.getName(), PURCHASE)) {
            System.out.println("代理商完成采购");
            result = (int) methodProxy.invokeSuper(o, objects);
        } else if (Objects.equals(method.getName(), SELL)) {
            System.out.println("代理商完成售卖");
            result = (int) methodProxy.invokeSuper(o, objects);
        }
        return result;
    });

    SuperMarket market = (SuperMarket) enhancer.create();
    market.selling(1L);
}

}



> 
> 注意:
> 
> 
> 1. 上面的代码里因为SuperMarketImpl类被增强,所以类名加上了EnhancerByCGLIB等信息。
> 2. 如果一个类没有实现接口,那么它就不能使用JDK动态代理,但是可以使用CGLIB动态代理。
> 
> 
> 


## 


## 静态织入(Static Weaving)


本工程使用了Springboot框架,加上@Service注解注入组件,使用自定义注解对方法进行环绕增强,详细可参看AOP原理。



@Service
public class SuperMarketImpl implements SuperMarket {
/**
* 商品成本列表
*/
private static final HashMap<Long, Integer> costMap = new HashMap<Long, Integer>() {
{
put(1L, 100);
put(2L, 200);
put(3L, 300);
}
};

@Override
public int purchasing() {
    System.out.println(this.getClass().getSimpleName() + " commodity ");
    return SUCCESS;
}

@Override
@EnhanceMethod(field = "test static weaving")
public int selling(Long id) {
    int price = costMap.get(id);
    if (Objects.isNull(price)) {
        System.out.println("the commodity id: " + id + " is not exist");
        return ERROR;
    }
    System.out.println(this.getClass().getSimpleName() + " commodity id: " + id + " price: " + price);
    return SUCCESS;
}

}


这里对selling动作进行增强,使用无侵入的方式,新建一个注解EnhanceMethod,其中元注解解释如下:



> 
> 
> ```
> @Target:描述注解的使用范围(即:被修饰的注解可以用在什么地方)
> @Retention:描述注解保留的时间范围(即:被描述的注解在它所修饰的类中可以被保留到何时)
> @Documented:描述在使用javadoc工具为类生成帮助文档时是否要保留其注解信息。
> @Inherited:使被它修饰的注解具有继承性(如果某个类使用了被@Inherited修饰的注解,则其子类将自动具有该注解)。
> 
> ```
> 
> 




@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface EnhanceMethod {
//注解传入的属性
String field() default “Static Weaving”;
}


增加切面类,AOP提供5种类型,这里使用环绕增强,对该方法增强只多打印两行日志(参数从切入点获取):


* 前置通知/增强(Before Advise)
* 后置通知(After Returning Advise)
* 环绕通知(Interception Around Advise)
* 异常抛出通知(Throws Advise)
* 引介通知(Introduction Advise)



@Component
@Aspect
public class EnhanceMethodAspect {

private static final String ANNOTATION_PATH = "@annotation(com.hust.zhang.example.EnhanceMethod)";
protected Logger logger = LoggerFactory.getLogger(this.getClass());

@Pointcut(ANNOTATION_PATH)
public void testPointcut() {

}

@SuppressWarnings({"unchecked", "rawtypes"})
@Around(ANNOTATION_PATH)
public Object around(ProceedingJoinPoint pjp) throws Throwable {

    //通过反射拿到目标方法的类名、方法名、参数、方法
    String clazz = pjp.getTarget().getClass().getSimpleName();
    String methodName = pjp.getSignature().getName();
    Object[] args = pjp.getArgs();

    logger.info("Invoke {}.{} and parameter is {}", clazz, methodName, args);

    Method method = ((MethodSignature) pjp.getSignature()).getMethod();
    EnhanceMethod myAnnotation = method.getAnnotation(EnhanceMethod.class);

    logger.info("my definition annotation is {}", myAnnotation);

    return pjp.proceed();

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

6)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值