aop面向切面编程,核心的东西是动态代理模式:cglib和jdk
先说aop的用法,百度搜索能够搜到很多相关用法的总结,下面简单的归类下aop的知识点:
基本概念:aspect(切面,属于某个模块的总称@aspect @configuration)、pointcut(表明要切入的切口点,具体用法见下文)、jointcut(连接点的概念,包括切入点传入的参数,属性,及返回值等)、advice(@around、@before、@after、@afterRetruning、@afterThrowing,这几个注解的用法不是很复杂,主要理清一下先后顺序就可以,顺序见下文)、weaving(织入的概念,其实就是加载进字节码,程序运行的时候能够找到,分为两种,分别是编译时增强(AspectJ)、运行时增强(CGLIB,spring aop为此种类型))、target object(被织者,很简单的概念,没有多余的东西)、aop proxy object(织入的过程,反向代理(本文主要要讲的理论,动态代理的代码很嗨,见下文))。
@pointcut
pointcut切点的表达式,语法有多种形式,其中包括:
1、excution([可见性(public/private/default)]+返回类型+[声明类型].方法名(参数)[异常] )其中[]可以不填,同时在切片表达式中可以添加&&、||、!进行拼接,也可以通过省略多个字符,..省略多个参数,+拼接多个类及其子类
@Pointcut("execution( com.cjm.model...(..))")
public void pointcut(){}
2、within:
3、this:
4、target:
5、args:
6、@within@target@args
7、annotation
8、bean:示例如下,其中指定了bean对象的名字被限定为person
上述除了execution起到执行功能外,其他的声明类型都是起到限制的作用,具体用法见链接https://www.cnblogs.com/zhaww/p/8674657.html。
@Pointcut("bean(person)")
public void pointcut(){}
@advice
主要有五种增强注解,按照织入顺序排序为:
around->before->around->after->afterReturning->afterThrowing
Jointcut
Jointcut中常用方法包括getArgs、getThis(返回代理对象)、getTarget、getSignature(返回被增强方法的相关信息),ProceedingJoinPoint继承自Jointcut,主要增加了proceed(可传入参数object[],用于传入目标方法的参数)方法,用于around增强时运行目标方法。
@around(pointcut="")
public around(ProceedingJoinPoint jp)
{
//before前
jp.proceed();//执行增强方法
//after前
}
aop proxy object
动态代理有两种类型,分别是CGLIB、JDK。其中JDK动态代理,是基于接口实现的,而CGLIB是基于继承类实现的。
jdk动态代理的简单举例,后续会研究一下反射的具体实现:
public class jdkTest {
public static void main(String[] args){
proxytest1 proxytest1 = new test1();
proxytest proxytest = new proxytest(proxytest1);
proxytest1 test= (proxytest1) Proxy.newProxyInstance(proxytest1.getClass().getClassLoader(),proxytest1.getClass().getInterfaces(),proxytest);
test.send();
}
}
其中proxytest1是接口:
public interface proxytest1 {
public void send();
}
test1时实现proxytest1接口的类:
public class test1 implements proxytest1 {
@Override
public void send(){
System.out.println("加油大兄弟,run");
}
}
代理类的实现如下:
public class proxytest implements InvocationHandler {
private Object test;
proxytest(Object test){
this.test = test;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
Object invoke = method.invoke(test,args);
return invoke;
}
}
通过该代理类,重写了invoke方法,并通过Proxy.newProxyInstance方法传入ClassLoader、interfaces和invocationHandler,并返回对应的接口对象中,当接口对象调用方法时,会调用invoke函数,动态加载该方法。
CGLIB动态代理主要是通过类继承来实现的:
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Landlord.class);
enhancer.setCallback(intermediary);//intermediary继承自MethodInterceptor并重写了intercept方法
Landlord rentProxy = (Landlord) enhancer.create();
rentProxy.rent();










网友评论