Spring中AOP的原理?

面试问Spring中AOP的原理?用到哪些技术?
答:通过动态代理技术,然后简单说了些实现方式。
这只是其中的一种,还有其他的吗?
答:........
求大哥们指点!

3个回答

其实它的代理 :分为动态代理和静态代理

cglib代理

[code="java"]
spring 提供了多种不同的方案实现对 bean 的 aop proxy, 包括 ProxyFactoryBean, 便利的 TransactionProxyFactoryBean 以及 AutoProxyCreator 等,
下图是 proxy class diagram 以供参考

这里重点说一下最常用的 ProxyFactoryBean, TransactionProxyFactoryBean, BeanNameAutoProxyCreator, DefaultAdvisorAutoProxyCreator 的联系和区别

  1. ProxyFactoryBean : 使用率最高的 proxy 方式, 它通过配置 interceptorNames 属性决定加入哪些 advisor (method interceptor 将会被自动包装成 advisor, 下文将描述这个细节), 注意是 "interceptorNames" 而不是 "interceptors",

原因是 ProxyFactoryBean 可能返回非 singleton 的 proxy 实例, 而 advisior 可能也是非 singleton 的,

因此不能通过 interceptor reference 来注入

  1. TransactionProxyFactoryBean : 特定用于 transaction proxy, 注意其 super class 是 AbstractSingletonProxyFactoryBean, 也就是说,

TransactionProxyFactoryBean 永远无法返回非 singleton 的 proxy 实例 !!!

如果你需要非 singleton 的 proxy 实例, 请考虑使用 ProxyFactoryBean.

  1. BeanNameAutoProxyCreator : 故名思义, 根据 bean name 进行 auto proxy, bean name 的 match 规则参见 org.springframework.util.PatternMatchUtils

  2. DefaultAdvisorAutoProxyCreator : 更强大的 auto proxy creator, 强大之处在于它会 cahce 容器中所有注册的 advisor, 然后搜索容器中所有的 bean ,
    如果某个 bean 满足 advisor 中的 Pointcut, 那么将会被自动代理, 与 BeanNameAutoProxyCreator 相比, 省去了配置 beanNames 的工作,

引用:
eg :















com.mycompany.FooService.*





      <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
          <bean id="defaultPointcutAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor" scope="prototype">
                <property name="pointcut" ref="fooPointcut"/>
                <property name="advice" ref="fooAdvice"/>
            </bean> 

            <bean id="fooAdvice" class="com.mycompany.FooAdvice" scope="prototype" />

            <bean id="fooPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut" scope="prototype">
                <property name="patterns">
                    <list>
                        <value>com.mycompany.FooService.*</value>
                    </list>
                </property>
            </bean>

以上配置将自动代理容器中所有 com.mycompany.FooService 类型的 bean, 并拦截其所有方法

深度话题

  1. MethodInterceptor 如何被包装成 Advisor ?

在 AdvisorAdapterRegistry#wrap(Object) 方法中实现, code as below
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {

if (adviceObject instanceof Advisor) {

return (Advisor) adviceObject;

}

if (!(adviceObject instanceof Advice)) {

hrow new UnknownAdviceTypeException(adviceObject);

}

Advice advice = (Advice) adviceObject;

if (advice instanceof MethodInterceptor) {

// So well-known it doesn't even need an adapter.

return new DefaultPointcutAdvisor(advice);

}

for (int i = 0; i < this.adapters.size(); i++) {

/ Check that it is supported.

AdvisorAdapter adapter = (AdvisorAdapter) this.adapters.get(i);

if (adapter.supportsAdvice(advice)) {

return new DefaultPointcutAdvisor(advice);

}

}

throw new UnknownAdviceTypeException(advice);

}

public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
hrow new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (int i = 0; i < this.adapters.size(); i++) {
/ Check that it is supported.
AdvisorAdapter adapter = (AdvisorAdapter) this.adapters.get(i);
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}

从代码可以看到, 如果 adviceObject(也就是 interceptorNames 对应的 bean) 不是 advisor
而是 MethodInterceptor 或 Advice, 那么 spring 将其包装成 DefaultPointcutAdvisor,
而 DefaultPointcutAdvisor 中定义的 Pointcut 是 TruePointcut :
class TruePointcut implements Pointcut, Serializable {

public static final TruePointcut INSTANCE = new TruePointcut();    

/**   
 * Enforce Singleton pattern.   
 */   
private TruePointcut() {    
}    

public ClassFilter getClassFilter() {    
    return ClassFilter.TRUE;    
}    

public MethodMatcher getMethodMatcher() {    
    return MethodMatcher.TRUE;    
}    

/**   
 * Required to support serialization. Replaces with canonical   
 * instance on deserialization, protecting Singleton pattern.   
 * Alternative to overriding <code>equals()</code>.   
 */   
private Object readResolve() {    
    return INSTANCE;    
}    

public String toString() {    
    return "Pointcut.TRUE";    
}    

}

[/code]

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!