参考 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. nagios监控mysql及邮件报警

    1.使用默认监控命令check_http命令+相关的参数来实现,如下: 在command.cfg添加如下关键词监控命令:check_http_word,参数解析:-I指定IP或者主机名,-u指定URL ...

  2. GitHub下载提速

    通过修改hosts文件来提速(该方法也可加速其他因为CDN被屏蔽导致访问慢的网站) 第一步:获取GitHub的IP地址 通过访问:http://tool.chinaz.com/dns或者https:/ ...

  3. echarts简单的折线图

    加jar包 <script src="<%=path %>/js/echarts.min.js"></script> 首先 在jsp页面中 选好 ...

  4. 【JAVA】String[]配列の相関

    配列の作成: ①String[] str = new String[5]; ②String[] str = new String[]{"","","& ...

  5. 浏览器虚拟过程IP插件

    浏览器虚拟过程 这是个插件在调用API时候结合使用,比如调用大量IP去点击http://www.opew.cn和http://www.gtev.cn function QMPlugin.gbip() ...

  6. Cocos2dx开发之运行与渲染流程分析

    学习Cocos2dx,我们都知道程序是由 AppDelegate 的方法 applicationDidFinishLaunching 开始,在其中做些必要的初始化,并创建运行第一个 CCScene 即 ...

  7. SpringMVC的执行流程

    解析SpringMVC执行流程 SpringMVC的执行图大概如下所示 1.首先它是由客户端发起请求,到DispatcherServlet,被拦截后到HandlerMapping这里充当一个路由器,通 ...

  8. Android辅助开发工具合集

    https://github.com/389273716/android-skill-summary/blob/master/开发工具使用指南/辅助开发工具.md

  9. 52-2018 蓝桥杯省赛 B 组模拟赛(一)java

    最近蒜头君喜欢上了U型数字,所谓U型数字,就是这个数字的每一位先严格单调递减,后严格单调递增.比如 212212 就是一个U型数字,但是 333333, 9898, 567567, 313133131 ...

  10. Busybox构建根文件系统和制作Ramdisk

      定制根文件系统的方法很多,最常用的是使用BusyBox来构建定制根文件系统.它集成压缩了Linux的许多工具和命令,可以使用户迅速方便地建立一套相对完整.功能丰富的文件系统,其中包括大量常用的应用 ...