既有适合小白学习的零基础资料,也有适合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();
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
6)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!