接上篇# 源码解析:AOP
cglib类代理
使用cglib实现的代理与jdk代理类似,只是代理对象的构造方式不同。
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
// 如果目标类已是cglib生成的代理类,那么继续向上查找
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
// 验证方法,如果存在无法继承的方法,如final,static,打印日志信息
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
// 使用入参给定的类加载器加载类,如果不为空
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
// 获取回调,即各种方法拦截器
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 | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
enhancer.setInterceptDuringConstruction(false);
enhancer.setCallbacks(callbacks);
return (this.constructorArgs != null && this.constructorArgTypes != null ?
enhancer.create(this.constructorArgTypes, this.constructorArgs) :
enhancer.create());
}
Spring使用ObjenesisCglibAopProxy
拓展了CglibAopProxy
,并从4.0开始作为默认选项。它覆写了CglibAopProxy
的createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks)
方法,使用Objenesis创建cglib代理对象。
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
Class<?> proxyClass = enhancer.createClass();
Object proxyInstance = null;
// 默认为true,可以指定spring.objenesis.ignore为true使其返回false
if (objenesis.isWorthTrying()) {
try {
proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
}
catch (Throwable ex) {
logger.debug("Unable to instantiate proxy using Objenesis, " +
"falling back to regular proxy construction", ex);
}
}
if (proxyInstance == null) {
// Regular instantiation via default constructor...
try {
Constructor<?> ctor = (this.constructorArgs != null ?
proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
proxyClass.getDeclaredConstructor());
ReflectionUtils.makeAccessible(ctor);
proxyInstance = (this.constructorArgs != null ?
ctor.newInstance(this.constructorArgs) : ctor.newInstance());
}
catch (Throwable ex) {
throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
"and regular proxy instantiation via default constructor fails as well", ex);
}
}
((Factory) proxyInstance).setCallbacks(callbacks);
return proxyInstance;
}
createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks)
方法中较为重要的部分是getCallbacks
方法的调用,此方法的作用是获取方法拦截器,以增强对应的方法。
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Parameters used for optimization choices...
boolean exposeProxy = this.advised.isExposeProxy();
// 默认为false
boolean isFrozen = this.advised.isFrozen();
// 一般为true
boolean isStatic = this.advised.getTargetSource().isStatic();
// Choose an "aop" interceptor (used for AOP calls).
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// Choose a "straight to target" interceptor. (used for calls that are
// unadvised but can return this). May be required to expose the proxy.
Callback targetInterceptor;
if (exposeProxy) {
targetInterceptor = (isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
else {
targetInterceptor = (isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
// Choose a "direct to target" dispatcher (used for
// unadvised calls to static targets that cannot return this).
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, // for normal advice
targetInterceptor, // invoke target without considering advice, if optimized
new SerializableNoOp(), // no override for methods mapped to this
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen,
// then we can make some optimizations by sending the AOP calls
// direct to the target using the fixed chain for that method.
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap<>(methods.length);
// TODO: small memory optimization here (can skip creation for methods with no advice)
for (int x = 0; x < methods.length; x++) {
Method method = methods[x];
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(method, x);
}
// Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array.
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
return callbacks;
}
其中主要的callbacks如下:
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, // for normal advice
targetInterceptor, // invoke target without considering advice, if optimized
new SerializableNoOp(), // no override for methods mapped to this
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
aopInterceptor
用于获取拦截器链,然后进行组合并调用。
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
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);
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// 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 = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
targetInterceptor
用于没有advice的情况,根据静动态和exposeProxy
分为四种,下面是静态的两种:
private static class StaticUnadvisedInterceptor implements MethodInterceptor, Serializable {
@Nullable
private final Object target;
public StaticUnadvisedInterceptor(@Nullable Object target) {
this.target = target;
}
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object retVal = methodProxy.invoke(this.target, args);
return processReturnType(proxy, this.target, method, retVal);
}
}
private static class StaticUnadvisedExposedInterceptor implements MethodInterceptor, Serializable {
@Nullable
private final Object target;
public StaticUnadvisedExposedInterceptor(@Nullable Object target) {
this.target = target;
}
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
try {
oldProxy = AopContext.setCurrentProxy(proxy);
Object retVal = methodProxy.invoke(this.target, args);
return processReturnType(proxy, this.target, method, retVal);
}
finally {
AopContext.setCurrentProxy(oldProxy);
}
}
}
其他类型的callback不多描述,具体调用哪一个callback由ProxyCallbackFilter
决定:
public int accept(Method method) {
if (AopUtils.isFinalizeMethod(method)) {
logger.trace("Found finalize() method - using NO_OVERRIDE");
return NO_OVERRIDE;
}
if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
if (logger.isTraceEnabled()) {
logger.trace("Method is declared on Advised interface: " + method);
}
return DISPATCH_ADVISED;
}
// We must always proxy equals, to direct calls to this.
if (AopUtils.isEqualsMethod(method)) {
if (logger.isTraceEnabled()) {
logger.trace("Found 'equals' method: " + method);
}
return INVOKE_EQUALS;
}
// We must always calculate hashCode based on the proxy.
if (AopUtils.isHashCodeMethod(method)) {
if (logger.isTraceEnabled()) {
logger.trace("Found 'hashCode' method: " + method);
}
return INVOKE_HASHCODE;
}
Class<?> targetClass = this.advised.getTargetClass();
// Proxy is not yet available, but that shouldn't matter.
List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
boolean haveAdvice = !chain.isEmpty();
boolean exposeProxy = this.advised.isExposeProxy();
boolean isStatic = this.advised.getTargetSource().isStatic();
boolean isFrozen = this.advised.isFrozen();
if (haveAdvice || !isFrozen) {
// If exposing the proxy, then AOP_PROXY must be used.
if (exposeProxy) {
if (logger.isTraceEnabled()) {
logger.trace("Must expose proxy on advised method: " + method);
}
return AOP_PROXY;
}
Method key = method;
// Check to see if we have fixed interceptor to serve this method.
// Else use the AOP_PROXY.
if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) {
if (logger.isTraceEnabled()) {
logger.trace("Method has advice and optimizations are enabled: " + method);
}
// We know that we are optimizing so we can use the FixedStaticChainInterceptors.
int index = this.fixedInterceptorMap.get(key);
return (index + this.fixedInterceptorOffset);
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Unable to apply any optimizations to advised method: " + method);
}
return AOP_PROXY;
}
}
else {
// See if the return type of the method is outside the class hierarchy of the target type.
// If so we know it never needs to have return type massage and can use a dispatcher.
// If the proxy is being exposed, then must use the interceptor the correct one is already
// configured. If the target is not static, then we cannot use a dispatcher because the
// target needs to be explicitly released after the invocation.
if (exposeProxy || !isStatic) {
return INVOKE_TARGET;
}
Class<?> returnType = method.getReturnType();
if (targetClass != null && returnType.isAssignableFrom(targetClass)) {
if (logger.isTraceEnabled()) {
logger.trace("Method return type is assignable from target type and " +
"may therefore return 'this' - using INVOKE_TARGET: " + method);
}
return INVOKE_TARGET;
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Method return type ensures 'this' cannot be returned - " +
"using DISPATCH_TARGET: " + method);
}
return DISPATCH_TARGET;
}
}
}
cglib代理还提供了一个优化机制,如果isFrozen
为true,那么将创建一个固定的拦截链FixedChainStaticTargetInterceptor
,因为此时无法调用Advised
接口的方法增加或者删除Advise
或者Advice
,拦截链不会发生改变,因此之后调用方法时将不会每次都进行拦截链的获取。当然,之前在分析jdk代理时发现Spring也对拦截链进行了缓存,不过如果调用了Advised
接口中的增加删除方法,那么此缓存将会被移除,下一次调用将会重新获取拦截链。
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap<>(methods.length);
// TODO: small memory optimization here (can skip creation for methods with no advice)
for (int x = 0; x < methods.length; x++) {
Method method = methods[x];
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(method, x);
}
// Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array.
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
}
ProxyFactoryBean
Spring还提供了一种基于FactoryBean
的方式创建代理对象,即ProxyFactoryBean
。它对poincut
以及其所应用的advisor
, advice
等等提供了完全的控制。同时,如果你不需要这些特性,它也提供了最简单的配置方式,例如:
<bean id="personTarget" class="com.mycompany.PersonImpl">
<property name="name" value="Tony"/>
<property name="age" value="51"/>
</bean>
<bean id="myAdvisor" class="com.mycompany.MyAdvisor">
<property name="someProperty" value="Custom string property value"/>
</bean>
<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor">
</bean>
<bean id="person"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.mycompany.Person"/>
<property name="target" ref="personTarget"/>
<property name="interceptorNames">
<list>
<value>myAdvisor</value>
<value>debugInterceptor</value>
</list>
</property>
</bean>
你只需要提供target
,即需要被代理的目标对象以及interceptorNames
,即用于增强的advisor
, advice
等即可。
下面先介绍一下它的各种属性,与之前分析提到的类似:
-
proxyTargetClass
: 代理类或者代理接口 -
optimize
: 通过cglib创建代理时是否进行激进的优化,如果不没有完全理解此优化是如何处理的,那么不要使用它。这个属性只对cglib起作用,对jdk代理不起作用。 -
frozen
: 如果设置为true
,那么创建代理对象后无法改变拦截链。 -
exposeProxy
: 决定当前代理对象是否能够通过AopContext.currentProxy()
暴露给目标对象。 -
proxyInterfaces
: 需要代理的接口。如果不提供,spring会自己查找是否存在可用接口,如果没有则使用cglib代理。 -
interceptorNames
: 需要应用到此代理的Advisor
,Advice
等的bean名称。可以使用通配符*
,表示应用所有Advisor
,Advice
等;也可以使用xxx*
,应用名称前缀为xxx
的所有Advisor
,Advice
。 -
singleton
: 是否只返回一个唯一对象,无论getObject()
被调用多少次,默认为true
。
了解了它的属性后,让我们看一下它的核心方法getObject()
。
public Object getObject() throws BeansException {
// 初始化拦截链
initializeAdvisorChain();
// 创建单例或者原型
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.info("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}
此方法共分为两步:
- 初始化拦截器链。根据
interceptorNames
获取所有匹配的Advisor
- 根据
singleton
属性,创建单例或者原型代理对象。
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
if (this.advisorChainInitialized) {
return;
}
// 如果指定了interceptorNames属性
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");
}
// Materialize interceptor chain from bean names.
// 实例化拦截器链
for (String name : this.interceptorNames) {
if (logger.isTraceEnabled()) {
logger.trace("Configuring advisor or advice '" + name + "'");
}
// 如果为xxx*的形式,则增加所有匹配的Advisor
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 {
// If we get here, we need to add a named interceptor.
// We must check if it's a singleton or 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;
}
initializeAdvisorChain()
方法只会被调用一次,从BeanFactory
中获取Advisor
。如果拦截器名后缀为*
,那么将会进行通配符匹配。
private void addGlobalAdvisor(ListableBeanFactory beanFactory, String prefix) {
// 获取所有Advisor对象
String[] globalAdvisorNames =
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Advisor.class);
// 获取所有Interceptor对象,它是Advice的子接口
String[] globalInterceptorNames =
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Interceptor.class);
List<Object> beans = new ArrayList<>(globalAdvisorNames.length + globalInterceptorNames.length);
Map<Object, String> names = new HashMap<>(beans.size());
for (String name : globalAdvisorNames) {
Object bean = beanFactory.getBean(name);
beans.add(bean);
names.put(bean, name);
}
for (String name : globalInterceptorNames) {
Object bean = beanFactory.getBean(name);
beans.add(bean);
names.put(bean, name);
}
// 排序
AnnotationAwareOrderComparator.sort(beans);
// 获取匹配的Advisor并增加到拦截器链中
for (Object bean : beans) {
String name = names.get(bean);
if (name.startsWith(prefix)) {
addAdvisorOnChainCreation(bean, name);
}
}
}
private void addAdvisorOnChainCreation(Object next, String name) {
// We need to convert to an Advisor if necessary so that our source reference
// matches what we find from superclass interceptors.
Advisor advisor = namedBeanToAdvisor(next);
if (logger.isTraceEnabled()) {
logger.trace("Adding advisor with name '" + name + "'");
}
addAdvisor(advisor);
}
public void addAdvisor(Advisor advisor) {
int pos = this.advisors.size();
addAdvisor(pos, advisor);
}
@Override
public void addAdvisor(int pos, Advisor advisor) throws AopConfigException {
if (advisor instanceof IntroductionAdvisor) {
validateIntroductionAdvisor((IntroductionAdvisor) advisor);
}
addAdvisorInternal(pos, advisor);
}
private void addAdvisorInternal(int pos, Advisor advisor) throws AopConfigException {
Assert.notNull(advisor, "Advisor must not be null");
if (isFrozen()) {
throw new AopConfigException("Cannot add advisor: Configuration is frozen.");
}
if (pos > this.advisors.size()) {
throw new IllegalArgumentException(
"Illegal position " + pos + " in advisor list with size " + this.advisors.size());
}
this.advisors.add(pos, advisor);
updateAdvisorArray();
adviceChanged();
}
否则,进行常规的bean获取调用。此处对prototype
类型的Advisor
进行了一点特殊处理(同时ProxyFactoryBean
的singletion
属性也需要为false
),即只进行占位,并不直接实例化它。
advice = new PrototypePlaceholderAdvisor(name);
public PrototypePlaceholderAdvisor(String beanName) {
this.beanName = beanName;
this.message = "Placeholder for prototype Advisor/Advice with bean name '" + beanName + "'";
}
单例
单例对象只创建一次,创建完成后将被缓存,之后每次调用都返回此对象。
private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
// 获取TargetSource
this.targetSource = freshTargetSource();
// 自动检测接口
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// Initialize the shared singleton instance.
super.setFrozen(this.freezeProxy);
// 创建代理对象
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
获取TargetSource
分两种情况,第一种情况也是最常见的情况为指定了target
属性,此时Spring将会从容器中获取此bean并将它包装为TargetSource
对象(默认为SingletonTargetSource
),当然,如果这个bean已经是TargetSource
对象,那么只需要执行转换即可。第二种情况则是指定了targetSource
属性,此时可以直接返回此对象。通过第二种方式,你可以自定义需要的TargetSource
或者使用Spring提供的几个TargetSource
(比如common,threadlocal等),以达成相应的需求。
private TargetSource freshTargetSource() {
if (this.targetName == null) {
if (logger.isTraceEnabled()) {
logger.trace("Not refreshing target: Bean name not specified in 'interceptorNames'.");
}
return this.targetSource;
}
else {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve target with name '" + this.targetName + "'");
}
if (logger.isDebugEnabled()) {
logger.debug("Refreshing target with name '" + this.targetName + "'");
}
Object target = this.beanFactory.getBean(this.targetName);
return (target instanceof TargetSource ? (TargetSource) target : new SingletonTargetSource(target));
}
}
接下来,如果你没有设置proxyInterfaces
属性,那么Spring将会自动检查目标对象实现的接口并设置。
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
public static Class<?>[] getAllInterfacesForClass(Class<?> clazz, @Nullable ClassLoader classLoader) {
return toClassArray(getAllInterfacesForClassAsSet(clazz, classLoader));
}
// 此方法会查找clazz实现的所有接口及其父接口
public static Set<Class<?>> getAllInterfacesForClassAsSet(Class<?> clazz, @Nullable ClassLoader classLoader) {
Assert.notNull(clazz, "Class must not be null");
// 如果clazz本身是一个接口,那么将返回它自己
if (clazz.isInterface() && isVisible(clazz, classLoader)) {
return Collections.singleton(clazz);
}
Set<Class<?>> interfaces = new LinkedHashSet<>();
Class<?> current = clazz;
while (current != null) {
Class<?>[] ifcs = current.getInterfaces();
for (Class<?> ifc : ifcs) {
if (isVisible(ifc, classLoader)) {
interfaces.add(ifc);
}
}
current = current.getSuperclass();
}
return interfaces;
}
public void setInterfaces(Class<?>... interfaces) {
Assert.notNull(interfaces, "Interfaces must not be null");
this.interfaces.clear();
for (Class<?> ifc : interfaces) {
addInterface(ifc);
}
}
/**
* Add a new proxied interface.
* @param intf the additional interface to proxy
*/
public void addInterface(Class<?> intf) {
Assert.notNull(intf, "Interface must not be null");
if (!intf.isInterface()) {
throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface");
}
if (!this.interfaces.contains(intf)) {
this.interfaces.add(intf);
adviceChanged();
}
}
接下来,便是之前说过的根据情况使用jdk或者cglib创建代理对象。
原型
原型对象创建的过程与单例类似,不过多执行了一步拷贝操作。对于一个新的原型对象,需要拷贝一份配置信息,一份拦截器链以及一个TargetSource
。当你使用原型模式时,你需要提供一个原型TargetSource
以及原型Advisor
,此时你的每一个代理对象都将是完全独立的。当然,如果你的这些对象是无状态的,那么效果也类似,唯一可能的问题便是并发争用。
private synchronized Object newPrototypeInstance() {
// In the case of a prototype, we need to give the proxy
// an independent instance of the configuration.
// In this case, no proxy will have an instance of this object's configuration,
// but will have an independent copy.
if (logger.isTraceEnabled()) {
logger.trace("Creating copy of prototype ProxyFactoryBean config: " + this);
}
ProxyCreatorSupport copy = new ProxyCreatorSupport(getAopProxyFactory());
// The copy needs a fresh advisor chain, and a fresh TargetSource.
TargetSource targetSource = freshTargetSource();
copy.copyConfigurationFrom(this, targetSource, freshAdvisorChain());
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
Class<?> targetClass = targetSource.getTargetClass();
if (targetClass != null) {
copy.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
}
copy.setFrozen(this.freezeProxy);
if (logger.isTraceEnabled()) {
logger.trace("Using ProxyCreatorSupport copy: " + copy);
}
return getProxy(copy.createAopProxy());
}
private List<Advisor> freshAdvisorChain() {
Advisor[] advisors = getAdvisors();
List<Advisor> freshAdvisors = new ArrayList<>(advisors.length);
for (Advisor advisor : advisors) {
// 如果是占位Advisor,此时真正获取其bean实例
if (advisor instanceof PrototypePlaceholderAdvisor) {
PrototypePlaceholderAdvisor pa = (PrototypePlaceholderAdvisor) advisor;
if (logger.isDebugEnabled()) {
logger.debug("Refreshing bean named '" + pa.getBeanName() + "'");
}
// Replace the placeholder with a fresh prototype instance resulting
// from a getBean() lookup
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve prototype advisor '" + pa.getBeanName() + "'");
}
Object bean = this.beanFactory.getBean(pa.getBeanName());
Advisor refreshedAdvisor = namedBeanToAdvisor(bean);
freshAdvisors.add(refreshedAdvisor);
}
else {
// Add the shared instance.
freshAdvisors.add(advisor);
}
}
return freshAdvisors;
}
其他
当创建完代理对象后,如果通过jdk代理创建,那么你可以将它转变为Advised
对象,并且对拦截器链进行增删操作;或者你可以直接获取ProxyFactoryBean
对象,并调用其方法增加接口或者修改拦截器链。此时,如果是singleton
模式,那么之前缓存的代理对象将会被清除,下一次调用getObject()
方法时将会获取一个新的代理对象,但是它们将会共享相同的拦截器链。如果修改的拦截器链,那么新旧两个代理对象还是会享有相同的配置;如果修改的是接口,那么新旧两个代理对象只有接口不同。如果是prototype
模式,那么将对之前获取的代理对象毫无影响,只会在下一个调用getObject()
方法时将会获取新代理对象。
关于ProxyFactoryBean
的更多信息,请查看6.4. Using the ProxyFactoryBean to Create AOP Proxies。