目录
从spring-aop讲起
了解spring-aop的同学应该都知道,aop的关键处理类是AbstractAutoProxyCreator,这个类实现了SmartInstantiationAwareBeanPostProcessor接口,SmartInstantiationAwareBeanPostProcessor接口继承了InstantiationAwareBeanPostProcessor接口,InstantiationAwareBeanPostProcessor接口继承了BeanPostProcessor,BeanPostProcessor中定义了关键的方法postProcessAfterInitialization。而AbstractAutoProxyCreator就是实现了这个关键方法。
AbstractAutoProxyCreator
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
这里只是简单的找一下ProxyFacotry的位置,对于spring-aop本身不做过多介绍。这里可以看到关键方法就是这个wrapIfNecessary,意为按需进行aop包装。
wrapIfNecessary()
/**
* Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
* @param bean the raw bean instance
* @param beanName the name of the bean
* @param cacheKey the cache key for metadata access
* @return a proxy wrapping the bean, or the raw bean instance as-is
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
其中getAdvicesAndAdvisorsForBean()就是获取advice、advisor的地方,比如用户定义的@Aspect切面,或Advisor的bean等,获取到拦截器后,创建代理对象proxy。
引出ProxyFactory
/**
* Create an AOP proxy for the given bean.
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @param specificInterceptors the set of interceptors that is
* specific to this bean (may be empty, but not null)
* @param targetSource the TargetSource for the proxy,
* already pre-configured to access the bean
* @return the AOP proxy for the bean
* @see #buildAdvisors
*/
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
关键来了,这里就是创建了ProxyFactory对象,proxyFactory.addAdvisors(advisors);添加切面,proxyFactory.getProxy()获取代理后的对象。可以说ProxyFactory是spring-aop较为底层的类,一般来说在应用中添加AOP也不是通过这种方式,而是使用切点、切面等。
下面正式进入ProxyFactory部分。
ProxyFactory如何使用
定义一个接口
public interface HelloService {
String sayHello(String params);
}
定义一个实现
@Service
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String params) {
return "from hessian:"+params;
}
}
接口实现类默认走Jdk Proxy
ProxyFactory pf = new ProxyFactory();
pf.setTarget(new HelloServiceImpl());
pf.setInterfaces(HelloService.class);
// 添加切面,在方法执行前打印一句话
// 注意这里是 org.aopalliance.intercept.MethodInterceptor;
pf.addAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("进来了");
return invocation.proceed();
}
});
// 获取代理后的对象
HelloService proxy = (HelloService) pf.getProxy();
System.out.println(proxy.getClass());
String sayHello = proxy.sayHello("111");
System.out.println(sayHello);
运行后打印:
class com.sun.proxy.$Proxy0
进来了
from hessian:111
切面成功加上了,代理后的类是个java Proxy。这是ProxyFactory的默认代理模式。
再加一个impl类,这个类不实现接口
@Service
public class HelloService0Impl {
public String sayHello(String params) {
return "from hessian:"+params;
}
}
非接口实现类走cglib:
ProxyFactory pf = new ProxyFactory();
pf.setTarget(new HelloService0Impl());
// 没有实现接口,默认就是cglib,不需要显式设置
// pf.setProxyTargetClass(true);
pf.addAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("进来了");
return invocation.proceed();
}
});
HelloService0Impl proxy = (HelloService0Impl) pf.getProxy();
System.out.println(proxy.getClass());
String sayHello = proxy.sayHello("111");
System.out.println(sayHello);
运行结果:
class demo.proxyfactory.HelloService0Impl$$EnhancerBySpringCGLIB$$70d3a6a1
进来了
from hessian:111
切面加上了,走的是cglib生成的proxy代理类。
强制走cglib
再编写一个,实现接口的类,但强制走cglib:
ProxyFactory pf = new ProxyFactory();
pf.setTarget(new HelloServiceImpl());
pf.setInterfaces(HelloService.class);
// 强制走cglib
pf.setProxyTargetClass(true);
pf.addAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("进来了");
return invocation.proceed();
}
});
HelloService proxy = (HelloService) pf.getProxy();
System.out.println(proxy.getClass());
String sayHello = proxy.sayHello("111");
System.out.println(sayHello);
运行结果:
class demo.proxyfactory.HelloServiceImpl$$EnhancerBySpringCGLIB$$fac980c9
进来了
from hessian:111
可以发现虽然实现了接口,但还是走了cglib的代理。
源码分析:
/**
* Create a new proxy according to the settings in this factory.
* <p>Can be called repeatedly. Effect will vary if we've added
* or removed interfaces. Can add and remove interceptors.
* <p>Uses a default class loader: Usually, the thread context class loader
* (if necessary for proxy creation).
* @return the proxy object
*/
public Object getProxy() {
return createAopProxy().getProxy();
}
/**
* Subclasses should call this to get a new AOP proxy. They should <b>not</b>
* create an AOP proxy with {@code this} as an argument.
*/
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// AopFactory这里是DefaultAopProxyFactory
return getAopProxyFactory().createAopProxy(this);
}
这里在拿到DefaultAopProxyFactory后,进入关键的逻辑了。
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 这里明确判断了,如果设置了proxyTargetClass为true,或者没有实现什么接口
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
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.");
}
// 但是如果目标类是个纯接口,那就只能走jdk proxy了,没法走cglib
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
// 没强制指定,或实现了接口了,就走jdk proxy
return new JdkDynamicAopProxy(config);
}
}
// 省略其他函数
}
JdkDynamicAopProxy
这里只看一下JdkDynamicAopProxy:
@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
这里有几个重点:
1.他代理的接口是通过AopProxyUtils.completeProxiedInterfaces()获取的列表
2.他自身实现了Jdk Proxy的InvocationHandler接口,所以重点关注他的invoke方法
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return 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;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
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.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && 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);
}
}
}
这个是重中之重了,理解了这个,再看ObjenesisCglibAopProxy也会容易许多。
1.target = targetSource.getTarget(); 这个获取目标对象。不管是通过proxyFactory.setTarget()还是proxyFactory.setTargetSource(),最终都是设置了一个TargetSource.
2.this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); #最关键处
调用链
这里获取了一个调用链。不用管他是怎么来的,他一定是把我们加的切面给包含了的。
然后创建一个ReflectiveMethodInvocation调用对象,里面有个currentInterceptorIndex从-1开始,他会按顺序调用完这些切面。
ReflectiveMethodInvocation
最后就是ReflectiveMethodInvocation了:
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// 如果已经到头了,就调用原method真实方法,因为是从-1开始的,切面数至少是1,至少走一次
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 按索引取拦截器
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;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
// 调用拦截器,拦截器最后一行是invocation.proceed(),也就是会再次回来.
return dm.interceptor.invoke(this);
}
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.
// 调用拦截器,拦截器最后一行是invocation.proceed(),也就是会再次回来.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
本篇到此结束,有问题欢迎一起讨论。