在Pointcut的基本接口定义中,需要返回一个MethodMatcher,来判断Point是否匹配,也就是说这个MethodMatcher来判断是否需要对当前方法调用进行增强或是否调用配置好 的通知,matches方法是MethodMatcher定义的接口方法
从上面的图可以看到,在proxy的invoke方法中,最终回去调用matches方法
①JDK实现动态代理:
必须继承InvocationHandler接口:
public interface InvocationHandler{
public object invoke(Object proxy,Method method,Object[] args)throws Throwable;
}
在Spring中,可以看到通过ProxyFactoryBean来完成代理的生成,可以使用JDK的Proxy和CGLIB两种生成方式
以ProxyFactoryBean的实现作为入口,是一条快速理解Spring Aop的学习之路
- 定义使用的通知器Advisor,这个通知器应该作为一个Bean来定义,定义了需要对对象进行增强的切面行为,也就是Advice通知
- 定义ProxyFactoryBean,它是封装Aop功能的注意类。在配置时,需要设置一些重要的属性,如proxy Interface,interceptorNames和target等
- 定义target属性,作为target属性注入的bean,是需要用AOP通知器中的切面来增强的对象
从FactoryBean中获取对象是以getObject()方法作为入口完成的,getObject()方法首先对通知链进行初始化,通知链封装了一系列的拦截器,从配置中读取,为代理对象的生成做好准备。因为Spring中有singleten类型和prototype两种类型,所以要对代理对象做一个区分
ProxyFactoryBean的getObject
@Override
public Object getObject() throws BeansException {
//初始化通知链
initializeAdvisorChain();
//这里对singleton和prototype的类型进行区分,生成对应的proxy
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}
初始化通知链
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
if (this.advisorChainInitialized) {
return;
}
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
}
// Globals can't be last unless we specified a targetSource using the property...
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
throw new AopConfigException("Target required after globals");
}
// 通过interceptorNames属性进行配置,这里是添加Adversor链的调用
for (String name : this.interceptorNames) {
if (logger.isTraceEnabled()) {
logger.trace("Configuring advisor or advice '" + name + "'");
}
if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}
else {
// 如果程序是在这里被调用,那么需要加入命名的拦截器advice,并检查
//这个Bean是singleton还是prototype类型
Object advice;
if (this.singleton || this.beanFactory.isSingleton(name)) {
// Add the real Advisor/Advice to the chain.
advice = this.beanFactory.getBean(name);
}
else {
// It's a prototype Advice or Advisor: replace with a prototype.
// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
advice = new PrototypePlaceholderAdvisor(name);
}
addAdvisorOnChainCreation(advice, name);
}
}
}
this.advisorChainInitialized = true;
}
生成singleton代理对象是在getSingletonInstance()代码中完成,针对target对象的方法调用会被这里生成的代理对象拦截
private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
this.targetSource = freshTargetSource();
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
//根据AOP框架来判断需要代理的接口
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
//这里设置dialing对象的接口
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// Initialize the shared singleton instance.
super.setFrozen(this.freezeProxy);
//这里调用proxyFactory来生成需要的proxy
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
//通过createAopProxy返回的AopProxy来得到代理对象
protected Object getProxy(AopProxy aopProxy){
return aopProxy.getProxy(this.proxyClasssLoader);
}
AopProxy是一个接口,具体由Cglib2AopProxy和JdkDynamicAopProxy实现
JdkDynamicProxy生成Proxy代理对象
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
这里是调用JDK生成proxy的地方
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
使用Cglib2AopProxy生成Proxy代理对象
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
}
//从advised中取得在Ioc容器中配的target对象
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
//验证代理对象的接口设置
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
//设置Enhancer对象,包括设置代理接口,会叫方法
//在理advised的Ioc配置,比如使用AOp的DynamicAdvisedInterceptor拦截器
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
this.advised.getTargetClass() + "]: " +
"Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
this.advised.getTargetClass() + "]: " +
"Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Exception ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
在AOP通过jdk和cglib方式生成代理对象时,相关的拦截器已经设置到代理对象中去了,拦截器在代理对象中起作用正是通过对这些方法的回调的完成的
如果是jdk生成的代理对象,则是通过InvocationHandler来设置,如果是Cglib,则是通过DynamicAdvisedInterceptor来完成回调
jdk的回调
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class<?> targetClass = null;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
//如果目标对象没事实现Object类的equals方法
return equals(args[0]);
}
if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// 如果目标对象没事实现hashCode方法
return hashCode();
}
if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
//根据代理对象的配置来调用服务
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// May be null. Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
// 获取定义好的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
//如果没有设置拦截器,那么直接调用target的对应方法
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
}
else {
// 如果有设置拦截器,调用拦截器后才调用目标方法
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
//沿着拦截器链继续前进
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
可以看到invokeJoinpointUsingReflection方法最终调用的是method.invoke()方法
在对拦截器链的调用时,都是通过ReflectiveMethodInvocation中通过proceed方法实现的
步骤:
- 初始化拦截器链
- 根据接口生成对应的代理对象,
- 在代理对象中,若有拦截器链则先调用拦截器链,判断是否方法需要增强,然后调用对应的方法