问题一、何时生成代理bean??
在getBean()过程中,进行了bean的实例化、依赖注入、初始化后,通过bean后处理器进行生成代理类。
在getBean()过程中的AbstractAutowireCapableBeanFactory类的 createBean ->doCreateBean 方法完成bean的创建和依赖注入后,进入initializeBean方法进行初始化
在初始化bean后,在bean后处理器的applyBeanPostProcessorsAfterInitialization生成代理bean , AbstractAutoProxyCreator 实现了SmartInstantiationAwareBeanPostProcessor后处理器接口调用wrapIfNecessary 根据切点判断是否有匹配到bean的Advisor通知器(包含通知和切点Advices只是通知) ,如果匹配到进行创建代理类。
创建代理调用createProxy方法里通过
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.addAdvisor(advisor);
proxyFactory.setTargetSource(targetSource);
return proxyFactory.getProxy(getProxyClassLoader());//生成代理
DefaultAopProxyFactory类来返回实际创建代理类,如果是有目标类有接口实现是通过JDK代理实现,否则是CGliB实现
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {//配置文件配置Optimize或者ProxyTargetClass或者没有配置代理接口
Class> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {//如果目标类有接口
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
JdkDynamicAopProxy类方法创建代理类,该类继承了InvocationHandler接口实现了invoke拦截方法
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, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);//经典JDK代理
}
通过配置方法默认是采用ProxyFactory 生成代理bean,
proxyFactoryBean是提供用户自定义配置方式的生成方式。
------------------------------------------------------------------------------------------到此bean的代理类已经生成完毕--------------------------------------------------------------------------------------------------
二、代理类如何外出增强业务逻辑??切面如何织入业务中??
生成代理类后,接口是注入的代理类,在调用方法时,会被代理类的invoke方法拦截。
1、通过proxyFactoryBean生成代理bean.
1)、拦截器链的初始化:通过配置文件取得配置文件中的advisor通知器。2)、通过JDK生成代理对象3)、代理对象实现了InvocationHandler接口。3)、在调用目标方法时invoke方法被触发5)、通过方法匹配获得拦截器链list 6)、通过递归循环调用拦截链list ,如果没有拦截链可以调用了就调用通过反射目标方法本身 。这样把增强逻辑织入进业务了。
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)) {//如果目标没有实现equles方法则采用代理类自带的方法
// The target does not implement the equals(Object) method itself.
return equals(args[0]);//判断逻辑:如果比较类是非JDK代理类直接返回false,如果是JDK代理类,且是自身返回true,否则比较两个代理的advised是否相同。
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {//如果I目标没有实现hashCode方法,采用代理类的hashcode方法
// The target does not implement the hashCode() method itself.
return hashCode();//JdkDynamicAopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
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();
}
// Get the interception chain for this method.
List
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ReflectiveMethodInvocation类,递归回调循环拦截链,如果拦截链调用完毕执行目标方法,这样把切面方法增强到业务逻辑中
protected ReflectiveMethodInvocation(
Object proxy, Object target, Method method, Object[] arguments,
Class> targetClass, List
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
//从-1开始看目前的拦截器链是否调用完毕。如果调用完毕,执行目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();//调用目标方法AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {//动态匹配连接点,如果匹配成功,
return dm.interceptor.invoke(this);//调用适配的advice拦截方法。
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();//递归调用拦截链
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);//如果是环绕类型的直接调用
}
}
-----------------------------------------------------------------------------------------
适配的 拦截类例如
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
private final AfterReturningAdvice advice;
/**
* Create a new AfterReturningAdviceInterceptor for the given advice.
* @param advice the AfterReturningAdvice to wrap
*/
public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();//递归调用
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());//执行增强方法
return retVal;
}
}
Spring看第一遍源码云里雾里的有些晕,再看看基础,基础应用深了,在dug源码就看明白了。
总结:JDK代理,代理类实现了所有实现接口方法,包括继承的父类实现的接口。不是接口的方法不会进行代理拦截。
hashcode、equales方法代理类不重写的话,用spring默认的方法且不进行拦截增强,如果重新会进行拦截增强。
AOP源码学习解析:学习参考博客:https://www.cnblogs.com/wade-luffy/p/5767092.html#_label1
http://www.codeweblog.com/spring-aop%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90-%E5%9B%9B-spring-aop%E7%9A%84jdk%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86/