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. chromerdriver下载地址:xpath_help

    chrome下载地址 http://npm.taobao.org/mirrors/chromedriver xpath_help https://blog.csdn.net/Cayny/article ...

  2. hdu3709 数位dp

    枚举fix所在的位置loc即可,然后数位dp即可 这题要注意一种特殊情况,就是所有位都是0的时候对于每个fix都是成立的 /* dp[i][j][k]表示前i位确定了平衡点在第j位,前i位和为k fi ...

  3. 文本处理三剑客之awk(No.1)

    示例1:只查看test.txt文件内的第3到第7行的内容 awk '{if(NR>=3 && NR<=7) print $0}' test.txt #其中的$0是输出整个行 ...

  4. 使用SqlServer_Profiler跟踪慢查询

    使用SQLProfiler(事件探查器)跟踪数据库操作及慢查询 1:应用程序连接SQL SERVER数据库服务器: 2:打开SQL Profiler开启数据库事件跟踪: (1):打开SQL Serve ...

  5. docker hub加速访问设置

    前言:docker是国外的,虽然有个版本开源免费,但是其docker  hub还是在国外,刚刚安装后,拉镜像就会发现,连接请求超时,中断服务,这是因为防火墙的问题,所以要将源指向国内的知名docker ...

  6. 末学者笔记--Linux计划任务及压缩归档

    一.计划任务 1.介绍: (1)定义:简单说就是通过一些设置,来使linux系统定时执行一些操作与任务. (2)作用:一般可执行一些周期性操作,也可定期备份数据. (3)可使用的命令:常用为at和cr ...

  7. Log.isLoggable之一正确的使用姿势

    DEBUG方法比较当我们在做APP开发时,需要设置调试开关打印Log,下面我列举出3种方法: 方法一:直接赋值public static final boolean DEBUG = true;//fa ...

  8. [原创]Zynq AXI-CDMA测试结果

    经过研究与demo,在zynq上使用axi-cmda效率还是很高,测试报告如下所示 对于读取32KB,GP0和HP0的测试结果如下:

  9. python中的while循环和for循环

    1.while循环 Gif 演示 Python while 语句执行过程 while 语句时还有另外两个重要的命令 continue,break 来跳过循环,continue 用于跳过该次循环,bre ...

  10. spark DataFrame的创建几种方式和存储

    一. 从Spark2.0以上版本开始,Spark使用全新的SparkSession接口替代Spark1.6中的SQLContext及HiveContext接口来实现其对数据加载.转换.处理等功能.Sp ...