从前面的简单的分析之中,我们得知,在ioc创建好我们的切入点的bean之后,使用的并不是创建好的bean,而还会为他创建一个代理bean。这个代理bean中有其关于方法增强的属性。具体的代理bean的属性如下图所示。
可以清楚看到创建的代理对象中有相关的增强器。
再来看看增强器都有什么属性
增强器的类型 以及属于哪个切面类, 增强器在哪个方法上作用都有相关字段记录。
对于cglib代理来说。他会设置多个callback,同时就必须得有一个callbackFilter来告诉我们代理对象执行方法的时候,用哪一个callback。
在spring-aop中,他为我们设置了7个callback,而执行哪个callback在创建代理对象的时候的filter里面指定了规则。
具体代码在这一块
CglibAopProxy 135 line
//在创建代理对象之前,创建好callback,并且设置好callback的执行规则(也就是callbackFilter)
enhancer.setCallbackFilter(new CglibAopProxy.ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
//设置callback类型 (数组)
enhancer.setCallbackTypes(types);
return this.createProxyClassAndInstance(enhancer, callbacks);
具体的cglib如何创建代理对象以及使用 看我最后的demo就ok
至于每个callback的作用我们就不做分析了。重点是我们的目标方法执行的话,会触动第一个callback的执行。
所以我来来看看代理对象的创建,以及代理对象的使用。
代理对象的创建
AbstractAutoProxyCreator 174 line
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
//bean是否有相关切面的注解 没有才会进入到这里
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
//获取方法增强器
//1、获取所有的增强器
//2、获取正处理的类的所有方法
//3、遍历,判断有没有方法与增强器匹配,有的话,则收集起来,返回。没有,返回DO_NOT_PROXY
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
//需要代理,将beanName先放在map中
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//创建代理对象
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
//将代理对象也收集在map中
this.proxyTypes.put(cacheKey, proxy.getClass());
//返回代理对象。最终ioc里面持有的就是这一块创建的代理对象
return proxy;
} else {
//不需要代理,直接返回bean
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
1、判断bean是否需要代理
这一块就不分析代码了,直接看流程图
2、代理对象的创建
这一块就不分析代码了,直接看流程图
注意! 创建代理对象的时候,如果bean没有实现接口,则使用cglib创建代理对象
如果bean有实现接口,那么就使用jdk创建代理对象
上面我们的流程演示的是使用cglib创建代理对象的过程。
3、代理对象的使用

4、jdk动态代理与cglib动态代理demo
4.1 jdk动态代理
/**
* @author 蒙ym
* @Date 2021/1/27
*/
public class JdkProxy implements InvocationHandler {
private Object targetClass;
public JdkProxy(Object targetClass){
//设置代理类
this.targetClass = targetClass;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//执行目标方法
Object result = method.invoke(targetClass, args);
return result;
}
public Object createProxy(){
//创建代理对象 这里是基于接口来创建的
return Proxy.newProxyInstance(targetClass.getClass().getClassLoader(), targetClass.getClass().getInterfaces(), this);
}
}
4.2 cglib动态代理
这里需要的jar包括:asm-3.3.1.jar与cglib-2.2.2.jar
**
* @author 蒙ym
* @Date 2021/1/27
*/
public class CglibProxy implements MethodInterceptor {
public Object createProxy(Class<?> clazz){
Enhancer enhancer = new Enhancer();
//设置回调函数,也就是代理对象方法执行的类
enhancer.setCallback(this);
//设置需要代理的类
enhancer.setSuperclass(clazz);
//将构造函数的参数类型放在这里面
Class[] type = {String.class};
//将构造函数传的值放在这里面
Object[] param = {"许嵩"};
//创建代理对象
return enhancer.create(type, param);
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//注意!这里需要使用最后一个参数来调invoke。
//如果使用第二个参数,那么相当于代理对象再执行一边目标方法,然后再次来到这个intercept方法 最终形成死循环
Object result = methodProxy.invokeSuper(o, objects);
return result;
}
}
测试动态代理
/**
* @author 蒙ym
* @Date 2021/1/27
*/
public class MainTest {
public static void main(String[] args) {
//测试jdk动态代理
JdkProxy proxy = new JdkProxy(new XuSong("许嵩"));
Star star =(Star) proxy.createProxy();
star.sing();
//测试cglib动态代理
CglibProxy cglib = new CglibProxy();
Star cglibProxy =(Star) cglib.createProxy(XuSong.class);
cglibProxy.sing();
}
}
代理接口与代理类
public interface Star {
/**
* 给定一个方法
* @return
*/
void sing();
}
public class XuSong implements Star {
private String name;
public XuSong(String name){
this.name = name;
}
@Override
public void sing() {
System.err.println("歌手名字: " + this.name);
}
}
查看下结果
再来做一个有多个callback的demo
/**
* @author 蒙ym
* @Date 2021/1/28
* @Desc callback--one
*/
public class CglibCallBack1 implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.err.println("callBack1的方法执行~~~");
return methodProxy.invokeSuper(o, objects);
}
}
/**
* @author 蒙ym
* @Date 2021/1/28
* @Desc callback--two
*/
public class CglibCallBack2 implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.err.println("callBack2的方法执行~~~");
return methodProxy.invokeSuper(o, objects);
}
}
callback–one 与 callback–two 一模一样,就是日志打印不一样
再来看看测试类怎么写
/**
* @author 蒙ym
* @Date 2021/1/27
*/
public class MainTest {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(XuSong.class);
Class[] clazz = {String.class};
Object[] param = {"许嵩"};
//创建callback类型的数组,用来存放我们的callback
Callback[] callbacks = new Callback[2];
//依次创建好两个callback
CglibCallBack1 back1 = new CglibCallBack1();
CglibCallBack2 back2 = new CglibCallBack2();
//将callback放入数组中
callbacks[0] = back1;
callbacks[1] = back2;
//设置好callback
enhancer.setCallbacks(callbacks);
//设置callback的filter 这个filter决定了最终执行目标方法的时候,会走到哪一个callback中
enhancer.setCallbackFilter(new CallbackFilter() {
@Override
public int accept(Method method) {
//打印下都会有哪些方法
System.out.println("打印方法----》" + method.toString());
//返回需要执行的callback在callback数组中的下标
//这个下标所在的callback就是最终执行逻辑的callback
return 1;
}
});
XuSong proxy =(XuSong) enhancer.create(clazz, param);
proxy.sing();
}
看下结果
至此,aop相关的就结束了,理解的很粗糙,只是大概的流程