spring aop 的代理工厂
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
相关内容
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 的代理工厂的更多相关文章
- 死磕Spring之AOP篇 - Spring AOP自动代理(二)筛选合适的通知器
该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...
- 死磕Spring之AOP篇 - Spring AOP自动代理(三)创建代理对象
该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...
- Hibernate 延迟加载的代理模式 和 Spring AOP的代理模式
Hibernate 延迟加载的代理模式 和 Spring AOP的代理模式 主题 概念 Hibernate 延迟加载的代理模式 Spring AOP的代理模式 区别和联系 静态代理和动态代理 概念 代 ...
- 死磕Spring之AOP篇 - Spring AOP自动代理(一)入口
该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...
- SSM-Spring-11:Spring中使用代理工厂Bean实现aop的四种增强
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 说说那四种增强:前置增强,后置增强,环绕增强,异常增强 那什么是代理工厂bean呢? org.springfr ...
- Spring AOP(基于代理类的AOP实现)
#基于代理类的AOP实现:step1: 1 package com.sjl.factorybean; /**切面类*/ import org.aopalliance.intercept.MethodI ...
- 代理实现aop以及代理工厂实现增强
一.静态代理实现 1.接口(抽象主题) 2.接口的实现类(真实主题) 3.代理类(代理主题) 4.测试类: ApplicationContext context=new ClassPathXmlApp ...
- Spring AOP 动态代理 缓存
Spring AOP应用:xml配置及注解实现. 动态代理:jdk.cglib.javassist 缓存应用:高速缓存提供程序ehcache,页面缓存,session缓存 项目地址:https://g ...
- spring aop 动态代理批量调用方法实例
今天项目经理发下任务,需要测试 20 个接口,看看推送和接收数据是否正常.因为对接传输的数据是 xml 格式的字符串,所以我拿现成的数据,先生成推送过去的数据并存储到文本,以便验证数据是否正确,这时候 ...
随机推荐
- py2neo的使用(转)
转自:https://blog.csdn.net/sinat_26917383/article/details/79901207#24-%E7%B1%BB%E4%BC%BCset%E7%9A%84%E ...
- Android studio使用android:style/Theme.Dialog报错:You need to use a Theme.AppCompat theme (or descendant) with this activity. at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
查找原因是在activity java代码部分继承了compatactivity public class DialogActivity extends AppCompatActivity 但是在An ...
- Pandas透视表和交叉表
透视表 参数名 说明 values 待聚合的列的名称.默认聚合所有数值列 index 用于分组的列名或其他分组键,出现在结果透视表的行 columns 用于分组的列表或其他分组键,出现在结果透视表的列 ...
- Flipping an Image
Given a binary matrix A, we want to flip the image horizontally, then invert it, and return the resu ...
- C#移除URL上指定的参数
/// <summary> /// 移除URL上指定的参数,不区分参数大小写 /// </summary> public static ...
- Harry Potter and J.K.Rowling(半平面交+圆和矩形交)
Harry Potter and J.K.Rowling http://acm.hdu.edu.cn/showproblem.php?pid=3982 Time Limit: 2000/1000 MS ...
- 通信导论-IP数据网络基础(4)
IP地址的编址方法--IP地址+掩码地址=网络地址 分类的IP地址 每一类地址都由两个固定长度的字段组成,其中一个字段是网络号 net-id,标志主机或路由器所连接到的网络,另一个字段则是主机号 ho ...
- IDEA配置
关于IDEA的配置 配置注释模板 CTRL_SHIFT_S,在Live Templates中新增一个TemplateGroup,然后再新建两个模板,如下图: 新增cc-ClassComment /** ...
- 迁移virtualenv环境
记录一次将window上的virtualenv部署至LINUX服务器 前提 你已经使用virtualenv创建了一个虚拟的python运行环境,并且已经完成了你的应用的开发,现在需要将工程部署到服务器 ...
- mysql设置存储中文变成问号或者乱码
技术交流群: 816227112 问题: 解决办法: 修改my.ini 如果是my-default.ini 要重命名成my.ini 要注意顺序,有可能服务启动不起来 [mysqld] charact ...