AOP代理对象生成

 

 AOP(Aspect-OrientedProgramming,面向方面编程)是OOP(Object-Oriented Programing,面向对象编程)的良好补充与完善,后者侧重于解决

从上到下的存在明显层次逻辑关系的问题,而前者则侧重于由左至右的水平散布的无明显逻辑关系但具备相同行为的问题。AOP抽象的是相同的行为而非

关联的行为,用于提供通用服务支持,而非业务逻辑处理,其核心思想是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。

AOP植入有多种不同方式,主要分为以下三种方式:

  1. 编译期植入
  2. 类装载期植入
  3. 动态代理植入

Spring中AOP具体的配置过程,可通过以下途径:

  1. 配置ProxyFactoryBean,显式设置advisors, advice, target等
  2. 配置AutoProxyCreator,使用定义bean的方式不变,但是从容器中获得的是代理对象

 

最顶层是ProxyConfig是一个数据,这个数据基类为ProxyFactoryBean这样的子类提供了配置属性;

AdvisedSupport的封装了Aop对通知和通知器的相关操作,这些操作对于不同的Aop的代理对象的生成都是一样的,

但对于具体的Aop代理对象的创建,AdvisedSupport把它交给它的子类们去完成;对于ProxyCreatorSupport,

可以将它看成是其子类创建Aop代理对象的一个辅助类;具体的Aop代理对象的生成,根据不同的需要,

分别由ProxyFactoryBean、ProxyFactory、AspectJProxyFactory来完成 

 

AbstractAutoProxyCreator 实现了BeanPostProcessor,当系统比较复杂或者中需要进行aop织入的bean较多时,

简单采用ProxyFacotryBean无疑会增加很多工作量,同时由于要从ProxyFactoryBean获得代理对象,也会使应用

和Spring之间的耦合度增加,这样的情况下,自动Aop代理的方式就能发挥它巨大的优势了。 

 

一、AOP对象的生成

1.ProxyFactory是怎样得到代理类的

public Object getProxy() {
        return createAopProxy().getProxy();
}
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); }

 

 

 

2.ProxyFactoryBean是怎样获得代理类的

ProxyFactoryBean是在Spring IoC环境中。

    @Override
    public Object getObject() throws BeansException {
        initializeAdvisorChain(); //初始化通知器
        if (isSingleton()) {
            return getSingletonInstance();//依据定义生成单例的Proxy
        }
        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(); //这里依据定义生成prototype的Proxy
        }
    }

 

使用示例

 

 

public class SayMehthodInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println(" method对象:" + invocation.getMethod() );
        System.out.println(" invocation对象:" + invocation);
        return invocation.proceed();
    }
}



public static void proxyFactoryBean(){
    ProxyFactoryBean factory = new ProxyFactoryBean();
    
    //给代理工厂一个原型对象
    factory.setTarget(new Person());
    
    factory.addAdvisors(getAdvisor());
    
    //从代理工厂中获取一个代理后的对象
    Person p = (Person) factory.getObject();
    p.say();
}

public static void proxyFactory(){
    ProxyFactory factory = new ProxyFactory();
    factory.setTarget(new Person());
    factory.addAdvisors(getAdvisor());

    Person p = (Person) factory.getProxy();
    p.say();
}

private static Advisor getAdvisor(){
    //切点
    JdkRegexpMethodPointcut cut = new JdkRegexpMethodPointcut();
    cut.setPatterns(new String[]{".*run.*",".*say.*"});//可以配置多个正则表达式

    //通知
    //Advice advice = new SayMehthodInterceptor();
    Advice advice = new CarLinkServiceInterceptor();

    //切面 = 切点 + 通知
    return  new DefaultPointcutAdvisor(cut, advice);

}

 

 

二、实现类比较

1. ProxyFactoryBean 

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

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

因此不能通过 interceptor reference 来注入 

2. TransactionProxyFactoryBean

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

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

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

3. BeanNameAutoProxyCreator

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

4. DefaultAdvisorAutoProxyCreator

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

5.InfrastructureAdvisorAutoProxyCreator

只解析spring 自身的 advisor, 用户自定义的不处理

 

三、org.aopalliance.intercept.MethodInterceptor 如何被包装成 Advisor 

    /**
     * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
     */
    public DefaultAdvisorAdapterRegistry() {
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }


    @Override
    public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
        if (adviceObject instanceof Advisor) {
            return (Advisor) adviceObject;
        }
        if (!(adviceObject instanceof Advice)) {
            throw 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 (AdvisorAdapter adapter : this.adapters) {
            // Check that it is supported.
            if (adapter.supportsAdvice(advice)) {
                return new DefaultPointcutAdvisor(advice);
            }
        }
        throw new UnknownAdviceTypeException(advice);
    }

 从代码可以看到, 如果 adviceObject(也就是 interceptorNames 对应的 bean) 不是 advisor 

而是 MethodInterceptor 或 Advice, 那么 spring 将其包装成 DefaultPointcutAdvisor, 

而 DefaultPointcutAdvisor 中定义的 Pointcut 是 TruePointcut .

也就是说, MethodInterceptor 和 Advice 被包装成的 Advisor 将会匹配容器中的所有 bean,

所以, 永远不要在 DefaultAdvisorAutoProxyCreator 的 interceptorNames 中引用一个 Advice,

那将会使容器中所有的 bean 被自动代理!!! 此时应该考虑使用 BeanNameAutoProxyCreator

 

 

 

 

 

参考:

网易乐得技术团队:Spring-SpringMVC父子容器&AOP使用总结

spring aop 代理对象生成

posted @ 2018-06-21 23:09 等风来。。 Views(...) Comments(...) Edit 收藏
------------------------------------------------------------------------------------------------------------ --------------- 欢迎联系 x.guan.ling@gmail.com--------------- ------------------------------------------------------------------------------------------------------------