参考 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. display:flex布局

    /*背景 居中 自适应 铺满容器*/ background: center / cover; flex布局是什么? flex是Flexibe Box 的缩写,意思为”弹性布局”, 用来为盒子模型提供最 ...

  2. 如何在Mac上用汇编语言写HelloWorld

    首先,Mac自带nasm,不过我们要先将其升级. 升级它的方法有很多种,因为我已经装好了homebrew,所以我直接在终端输入: brew install nasm 这样就升级啦- 接下来,创建一个H ...

  3. Swagger2 header 添加token

    @Bean public Docket apiDocument() { return new Docket(DocumentationType.SWAGGER_2) .groupName(" ...

  4. 关于处理java.lang.IllegalArgumentException at java.sql.Date.getHours异常

    https://segmentfault.com/a/1190000016937108

  5. Add `gem 'sqlite3'` to your Gemfile

    错误:Specified 'sqlite3' for database adapter, but the gem is not loaded. Add `gem 'sqlite3'` to your ...

  6. SQL 数据开发(经典)转贴

    数据开发(经典) 1.按姓氏笔画排序: Select * From TableName Order By CustomerName Collate Chinese_PRC_Str oke_ci_as ...

  7. I2C与SMBus

    关于I2C与SMBus,许多人很少去谈论与了解两者的细节差异,包括很多国外的简报,文章也经常将两者混写.交杂描述.交替运用. 确实,在一般运用下,I2C Bus与SMBus没有太大的差别,从实际接线上 ...

  8. input下拉框

    用Html5和css.js写的,引用的bootstrap和jquery文件请各位看客自己去下载

  9. Java多线程消费者、生产者的基本思路

    多线程主要考察的就是 线程的同步控制   生产者消费者的思路就是,当 一个线程执行时让另一个线程 挂起就行了 ThreadOne.ThreadTwo同时运行,添加一个变量在一个公共类(下边的Funct ...

  10. wpf 加载资源文件

    方法一:App.xaml页面上写 <Application x:Class="LanguageChange.App" xmlns="http://schemas.m ...