参考 https://docs.spring.io/spring/docs/4.3.11.RELEASE/spring-framework-reference/htmlsingle/#aop-understanding-aop-proxies

package org.springframework.aop.framework

public class ProxyFactory extends ProxyCreatorSupport {
...
}
public class ProxyCreatorSupport extends AdvisedSupport {

    private AopProxyFactory aopProxyFactory;

    ...

    /**
* Create a new ProxyCreatorSupport instance.
*/
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
} ...
}
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

    @Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
} ... }
boolean java.lang.reflect.Proxy.isProxyClass(Class<?> cl)

Returns true if and only if the specified class was dynamically generated to be a proxy class using the getProxyClass method or the newProxyInstance method. 

The reliability of this method is important for the ability to use it to make security decisions, so its implementation should not just test if the class in question extends Proxy.

Parameters:
cl the class to test
Returns:
true if the class is a proxy class and false otherwise
Throws:
NullPointerException - if cl is null

JDK 示例

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory; public class Main {
public static void main(String[] args) { ProxyFactory factory = new ProxyFactory(new SimplePojo());
factory.addInterface(Pojo.class);
factory.addAdvice(new SomeAdvice());
Pojo pojo = (Pojo) factory.getProxy(); // this is a method call on the proxy!
pojo.foo();
}
} class SimplePojo implements Pojo { @Override
public void foo() {
// this next method invocation is a direct call on the 'this' reference
this.bar();
} @Override
public void bar() {
// some logic...
System.out.println("barrrrrrrr");
} } interface Pojo {
public void foo(); public void bar();
} class SomeAdvice implements MethodInterceptor { @Override
public Object invoke(MethodInvocation invocation) throws Throwable {
String name = invocation.getMethod().getName();
System.out.println(name + " start");
Object proceed = invocation.proceed();
System.out.println(name + " end");
return proceed;
} }

运行结果:

foo start
barrrrrrrr
foo end

通过代理才会执行advise , 自调用(self-invocation 例如 this.bar())不会执行代理的advise 。

解决方式有两种,其一:

暴露代理(不推荐使用)

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.AopContext;
import org.springframework.aop.framework.ProxyFactory; public class Main {
public static void main(String[] args) { ProxyFactory factory = new ProxyFactory(new SimplePojo());
factory.addInterface(Pojo.class);
factory.addAdvice(new SomeAdvice());
factory.setExposeProxy(true);
Pojo pojo = (Pojo) factory.getProxy(); // this is a method call on the proxy!
pojo.foo();
}
} class SimplePojo implements Pojo { @Override
public void foo() {
// this works, but... gah!
((Pojo) AopContext.currentProxy()).bar();
} @Override
public void bar() {
// some logic...
System.out.println("barrrrrrrr");
} } interface Pojo {
public void foo(); public void bar();
} class SomeAdvice implements MethodInterceptor { @Override
public Object invoke(MethodInvocation invocation) throws Throwable {
String name = invocation.getMethod().getName();
System.out.println(name + " start");
Object proceed = invocation.proceed();
System.out.println(name + " end");
return proceed;
} }

运行结果:

foo start
bar start
barrrrrrrr
bar end
foo end

其二:

抽新类,避免自调用

CGLIB 示例

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory; public class Main {
public static void main(String[] args) { ProxyFactory factory = new ProxyFactory(new SimplePojo());
factory.addAdvice(new SomeAdvice());
SimplePojo pojo = (SimplePojo) factory.getProxy(); // this is a method call on the proxy!
pojo.foo();
}
} class SimplePojo { public void foo() {
this.bar();
} public void bar() {
// some logic...
System.out.println("barrrrrrrr");
} } class SomeAdvice implements MethodInterceptor { @Override
public Object invoke(MethodInvocation invocation) throws Throwable {
String name = invocation.getMethod().getName();
System.out.println(name + " start");
Object proceed = invocation.proceed();
System.out.println(name + " end");
return proceed;
} }

运行结果:

foo start
barrrrrrrr
foo end

暴露代理同JDK 动态代理

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.AopContext;
import org.springframework.aop.framework.ProxyFactory; public class Main {
public static void main(String[] args) { ProxyFactory factory = new ProxyFactory(new SimplePojo());
factory.addAdvice(new SomeAdvice());
factory.setExposeProxy(true);
SimplePojo pojo = (SimplePojo) factory.getProxy(); // this is a method call on the proxy!
pojo.foo();
}
} class SimplePojo { public void foo() {
((SimplePojo) AopContext.currentProxy()).bar();
} public void bar() {
// some logic...
System.out.println("barrrrrrrr");
} } class SomeAdvice implements MethodInterceptor { @Override
public Object invoke(MethodInvocation invocation) throws Throwable {
String name = invocation.getMethod().getName();
System.out.println(name + " start");
Object proceed = invocation.proceed();
System.out.println(name + " end");
return proceed;
} }

运行结果:

foo start
bar start
barrrrrrrr
bar end
foo end

相关内容

@Transactional 为什么会失效

https://docs.spring.io/spring/docs/4.3.11.RELEASE/spring-framework-reference/htmlsingle/#transaction-declarative-annotations

Method visibility and @Transactional

When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.

import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;import org.springframework.aop.framework.ProxyFactory;
public class Main {public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory(new SimplePojo());factory.addInterface(Pojo.class);factory.addAdvice(new SomeAdvice());factory.setExposeProxy(true);Pojo pojo = (Pojo) factory.getProxy();
// this is a method call on the proxy!pojo.foo();}}
class SimplePojo implements Pojo {
@Overridepublic void foo() {// this next method invocation is a direct call on the 'this' referencethis.bar();}
@Overridepublic void bar() {// some logic...System.out.println("barrrrrrrr");}
}
interface Pojo {public void foo();
public void bar();}
class SomeAdvice implements MethodInterceptor {
@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {String name = invocation.getMethod().getName();System.out.println(name + " start");Object proceed = invocation.proceed();System.out.println(name + " end");return proceed;}
}

spring aop 的代理工厂的更多相关文章

  1. 死磕Spring之AOP篇 - Spring AOP自动代理(二)筛选合适的通知器

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

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

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

  3. Hibernate 延迟加载的代理模式 和 Spring AOP的代理模式

    Hibernate 延迟加载的代理模式 和 Spring AOP的代理模式 主题 概念 Hibernate 延迟加载的代理模式 Spring AOP的代理模式 区别和联系 静态代理和动态代理 概念 代 ...

  4. 死磕Spring之AOP篇 - Spring AOP自动代理(一)入口

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

  5. SSM-Spring-11:Spring中使用代理工厂Bean实现aop的四种增强

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 说说那四种增强:前置增强,后置增强,环绕增强,异常增强 那什么是代理工厂bean呢? org.springfr ...

  6. Spring AOP(基于代理类的AOP实现)

    #基于代理类的AOP实现:step1: 1 package com.sjl.factorybean; /**切面类*/ import org.aopalliance.intercept.MethodI ...

  7. 代理实现aop以及代理工厂实现增强

    一.静态代理实现 1.接口(抽象主题) 2.接口的实现类(真实主题) 3.代理类(代理主题) 4.测试类: ApplicationContext context=new ClassPathXmlApp ...

  8. Spring AOP 动态代理 缓存

    Spring AOP应用:xml配置及注解实现. 动态代理:jdk.cglib.javassist 缓存应用:高速缓存提供程序ehcache,页面缓存,session缓存 项目地址:https://g ...

  9. spring aop 动态代理批量调用方法实例

    今天项目经理发下任务,需要测试 20 个接口,看看推送和接收数据是否正常.因为对接传输的数据是 xml 格式的字符串,所以我拿现成的数据,先生成推送过去的数据并存储到文本,以便验证数据是否正确,这时候 ...

随机推荐

  1. Node.js 薄荷网爬取

    Node.js:是一个基于前端的服务器,主要的特点:单线程,异步I/O(对这个没有了解,开发起来真的会踩很多坑),事件驱动 前言:本人主要是一个以使用.Net平台下的语言,进行开发的一个菜鸡,之前面试 ...

  2. css: box-sizing

    border-box 宽度包含了边框 content-box 边框不包含在内容区中,会增加到实际的宽度中

  3. 关于Linux 文件权限的思考

    Linux文件系统每个文件分为inode和block,inode中包含一些基本信息(文件名,类型,长度,修改时间,权限等待),并且指向包含文件真实内容的block,而目录是文件的一种,其block的内 ...

  4. aws

    名称 对应的技术 EC2 虚拟机技术 Virtual Machine 抽象了物理机,看到的是多台虚拟的机器 需要配置管理存储.网络.操作系统等 数分钟启动,运行数周或数月 ECS 容器 Contain ...

  5. springboot使用Redis,监听Redis键过期的事件设置与使用代码

    我使用的是Windows下的Redis服务,所以一下Redis设置都是在Windows平台进行. 1.修改Redis配置文件 1.1:Windows下的Redis存在两个配置文件 修改带有servic ...

  6. windows7 ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务 的解决方法

    用PL/SQL连接虚拟机中的Oracle数据库,发现又报了“ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务”错误,帮其解决后,发现很多人遇到过这样的问题,因此写着这里. 也许你没 ...

  7. rn最新版测试

    1.使用软件版本rn-4.20.4.zipdrago-4.22.03 2.启动drago选择菜单‘对弈’ -> ‘对弈引擎设置’,点按钮‘添加’,选择‘已安装’,输入:姓名‘rn-4.20.4’ ...

  8. 00.pt-toolkit 目录

    一. 好用便利的工具,常用 pt-align 对齐文本格式pt-archiver 循序渐进的归档表,删除表,迁移数据pt-config-diff 对比不同配置文件.服务器配置参数pt-diskstat ...

  9. Javaweb拦截器

    http://blog.csdn.net/reggergdsg/article/details/52962774

  10. Docker 容器连接

    前面我们实现了通过网络端口类访问运行在 diocker 容器内的服务.下面我们来实现通过端口连接到了一个 dokcer 容器. 网络端口映射 我们创建一个python应用的容器. runoob@run ...