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 代理对象生成

AOP代理对象生成的更多相关文章

  1. 深入理解Spring AOP之二代理对象生成

    深入理解Spring AOP之二代理对象生成 spring代理对象 上一篇博客中讲到了Spring的一些基本概念和初步讲了实现方法,当中提到了动态代理技术,包含JDK动态代理技术和Cglib动态代理 ...

  2. Spring进阶之路(10)-Advice简单介绍以及通过cglib生成AOP代理对象

    Advice简单介绍 1. Before:在目标方法运行之前运行织入.假设Before的处理中没有进行特殊的处理.那么目标方法终于会运行,可是假设想要阻止目标方法运行时.能够通过抛出一个异常来实现.B ...

  3. spring5 源码深度解析----- AOP代理的生成

    在获取了所有对应bean的增强后,便可以进行代理的创建了.回到AbstractAutoProxyCreator的wrapIfNecessary方法中,如下所示: protected static fi ...

  4. Spring AOP高级——源码实现(3)AopProxy代理对象之JDK动态代理的创建过程

    spring-aop-4.3.7.RELEASE  在<Spring AOP高级——源码实现(1)动态代理技术>中介绍了两种动态代理技术,当然在Spring AOP中代理对象的生成也是运用 ...

  5. AOP之proceedingjoinpoint和joinpoint区别(获取各对象备忘)、动态代理机制及获取原理代理对象、获取Mybatis Mapper接口原始对象

    现在AOP的场景越来越多,所以我们有必要理解下和AOP相关的一些概念和机制. import org.aspectj.lang.reflect.SourceLocation; public interf ...

  6. Spring AOP源码分析(三):基于JDK动态代理和CGLIB创建代理对象的实现原理

    AOP代理对象的创建 AOP相关的代理对象的创建主要在applyBeanPostProcessorsBeforeInstantiation方法实现: protected Object applyBea ...

  7. 死磕Spring之AOP篇 - Spring AOP自动代理(三)创建代理对象

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...

  8. Springboot源码分析之代理对象内嵌调用

    摘要: 关于这个话题可能最多的是@Async和@Transactional一起混用,我先解释一下什么是代理对象内嵌调用,指的是一个代理方法调用了同类的另一个代理方法.首先在这儿我要声明事务直接的嵌套调 ...

  9. Spring Aop(十二)——编程式的创建Aop代理之AspectjProxyFactory

    转发地址:https://www.iteye.com/blog/elim-2397922 编程式的创建Aop代理之AspectjProxyFactory 之前已经介绍了一款编程式的创建Aop代理的工厂 ...

随机推荐

  1. js-分享功能插件

    soshm 分享功能插件 地市:https://github.com/calledT/soshm yarn 安装:yarn add soshm -s;  引入:import soshm from ‘s ...

  2. SpringBoot图片上传(四) 一个input上传N张图,支持各种类型

    简单介绍:需求上让实现,图片上传,并且可以一次上传9张图,图片格式还有要求,网上找了一个测试了下,好用,不过也得改,仅仅是实现了功能,其他不尽合理的地方,还需自己打磨. 代码: //html<d ...

  3. ansible的delegate_to、connection、和local_action

    由于工作需要,经常需要把目标节点获得的信息写入执行节点文件日志. 所以经常用到delegate_to和connection,而local_action写法难看,基本不用. delegate_to和co ...

  4. 期货大赛项目|五,表格插件datatatables在MVC中的应用

    系统中都需要表格,我见过最好的表格就是Datatables了,但中文文档有限,英文能力有限,就写一些简单用法 上图看效果先 要了分页和排序 基本用法 引入js和css bundles.Add(new ...

  5. 美团小程序框架mpvue入门

    mpvue 主要特性 使用 mpvue 开发小程序,你将在小程序技术体系的基础上获取到这样一些能力: 1. 彻底的组件化开发能力:提高代码复用性 2. 完整的 Vue.js 开发体验 3. 方便的 V ...

  6. el内部支持运算表达式,外部不支持

    el内部支持运算表达式 如"${pageBean.currentPage==1}" "${pageBean.currentPage+1}"........ 外部 ...

  7. eclipse怎么对项目重命名,eclipse怎么重命名类

    eclipse怎么对项目重命名,eclipse怎么重命名类

  8. CentOS6.5安装图形用户界面

    CentOS 6.5 安装图形界面 安装的时候没有安装图像界面.安装步骤如下: 1.yum -y groupinstall Desktop 2.yum -y groupinstall "X ...

  9. cocos 游戏开发 (第一天作业)

    作业1——控制台游戏菜单 // 游戏菜单.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> ...

  10. JQuery 绑定单击事件到某个函数的的方法

    <script> function 我会在加载完页面马上执行() { alert('我会在加载完页面马上执行'); } function 我只会在按钮点击时才执行() { alert('我 ...