jdk动态代理与cglib代理、spring Aop代理原理-代理使用浅析
原创声明:本博客来源为本人原创作品,绝非他处摘取,转摘请联系博主
代理(proxy)的定义:为某对象提供代理服务,拥有操作代理对象的功能,在某些情况下,当客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
动态代理实现主要有2种形式,主要分为:
1.jdk动态代理:
1)原理:是根据类加载器和接口创建代理类(此代理类是接口的实现类,所以必须使用接口 面向接口生成代理,位于java.lang.reflect包下)
2)实现方式:
1. 通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(…);
2. 通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类Class clazz = Proxy.getProxyClass(classLoader,new Class[]{…});
3. 通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4. 通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
2~4步骤可合并
package proxy.jdkproxy; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import org.junit.Test; public class JDKProxy{
//写法1
private Object targetObject;//代理目标
public Object CustomerProxy(Object obj) {
targetObject = obj;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(),new targetHandler());
}
class targetHandler implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开启事务...");
Object returnValue = method.invoke(targetObject, args);//回调被代理目标的方法userDaoImpl.add();
System.out.println("提交事务");
return returnValue;
}
}
public static void main(String[] args) {
JDKProxy jdkProxy = new JDKProxy();
Customer userDao = (Customer)jdkProxy.CustomerProxy(new CustomerImpl());
userDao.shopping();
}
//写法2
@Test
public void test1(){
Customer customer = new CustomerImpl();
Customer cus = (Customer) Proxy.newProxyInstance(customer.getClass().getClassLoader(), customer.getClass().getInterfaces(),new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
return method.invoke(proxy, args);
} });
cus.shopping();
}
}
3)不足点:jdk动态代理,必须是面向接口,目标业务类必须实现接口
2.CGLIB代理
1.原理:利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
2.实现方法:
package proxy.cglib; import java.lang.reflect.Method; import org.junit.Test; import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import proxy.model.Customer; public class CGLIBProxy {
//写法1
private Object targetObject;
private Object createProxy(Object obj){
targetObject = obj;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetObject.getClass());//设置代理对象,父类,说明是继承,所有代理对象不能为final
enhancer.setCallback(new MyHandler());
return enhancer.create();//创建代理
}
class MyHandler implements MethodInterceptor{
@Override
public Object intercept(Object arg0, Method method, Object[] args,
MethodProxy arg3) throws Throwable {
System.out.println("开启事务..");
Object returnValue = method.invoke(targetObject, args);
System.out.println("提交事务....");
return returnValue;
}
}
@Test
public void test1() {
CGLIBProxy cglibProxy = new CGLIBProxy();
Customer customer = (Customer)cglibProxy.createProxy(new Customer());
customer.eat();
}
//写法2
@Test
public void test2(){
Customer customer = new Customer();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(customer.getClass());
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy arg3) throws Throwable {
if(method.getName().equals("eat")){
System.out.println("customer的eat方法被拦截了。。。。");
Object invoke = method.invoke(proxy, args);
System.out.println("真实方法拦截之后。。。。");
return invoke;
}
// 不拦截
return method.invoke(proxy, args);
}
});
Customer cus = (Customer) enhancer.create();
cus.eat();
}
}
3.注意点:被代理目标不是是final修饰的类(final修饰类不能被继承)
spring aop代理原理
1.注意点:
- 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
- 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
- 如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
2.强制把jdk代理转换成cglib代理
- 添加CGLIB库,SPRING_HOME/cglib/*.jar
- 在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class = "true" />
传统AOP有默认的实现代理机制,可不需要专门指定代理,如自定义代理对象,可在类生成的时候自动代理,自动代理的方式主要有2种,一种是基于Bean名称的自动代理BeanNameAutoProxyCreator,另外一种是基于切面信息的自动代理DefaultAdvisorAutoProxyCreator
spring mvc 使用DefaultAdvisorAutoProxyCreator实现自动代理 配置
<!--定义一个表示声明使用自动代理的类 -->
<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<!-- 定义代理类(本示例为异常类) -->
<bean id="exceptionHandler" class="com.kaizhi.platform.util.ExceptionHandler"/>
<!-- 定义支持正则表达式的通知 -->
<bean id="exceptionHandlerAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref bean="exceptionHandler"/>
</property>
<property name="patterns">
<value>.save*.*</value>//正则匹配需要拦截的方法
</property>
</bean>
spring mvc 使用BeanNameAutoProxyCreator自动代理配
<!-- 基于BeanNameAutoProxyCreator,Bean名称的自动代理 -->
<!-- 定义代理类 -->
<bean id="exceptionHandler" class="com.kaizhi.platform.util.ExceptionHandler"/>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<!-- 拦截的业务bean -->
<property name="beanNames" value="*adminFinanceService"/>
<!-- 拦截的通知 -->
<property name="interceptorNames" value="exceptionHandler"/>
</bean>
jdk动态代理与cglib代理、spring Aop代理原理-代理使用浅析的更多相关文章
- 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。
基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...
- Spring -- <tx:annotation-driven>注解基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)的区别。
借鉴:http://jinnianshilongnian.iteye.com/blog/1508018 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional ...
- Spring <tx:annotation-driven>注解 JDK动态代理和CGLIB动态代理 区别。
基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...
- spring AOP底层原理实现——jdk动态代理
spring AOP底层原理实现——jdk动态代理
- spring源码学习【准备】之jdk动态代理和cglib动态代理的区别和性能
一:区别:---->JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了.--->JDK的动态代理机制只能代理实现了接口的类,而不能 ...
- JDK动态代理和CGLIB代理的区别
一.原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 而cglib动态代理是利用asm开源包,对代理对象类的class文件 ...
- Spring AOP实现原理-动态代理
目录 代理模式 静态代理 动态代理 代理模式 我们知道,Spring AOP的主要作用就是不通过修改源代码的方式.将非核心功能代码织入来实现对方法的增强.那么Spring AOP的底层如何实现对方法的 ...
- jdk动态代理和cglib动态代理的区别
一.原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 而cglib动态代理是利用asm开源包,对代理对象类的class文件 ...
- java的静态代理、jdk动态代理和cglib动态代理
Java的代理就是客户端不再直接和委托类打交道,而是通过一个中间层来访问,这个中间层就是代理.使用代理有两个好处,一是可以隐藏委托类的实现:二是可以实现客户与委托类之间的解耦,在不修改委托类代码的情况 ...
- jdk 动态代理和 cglib 动态代理
原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 而cglib动态代理是利用asm开源包,对代理对象类的class文件加载 ...
随机推荐
- win10下安装mysql-5.7.25-winx64
Step1 官方下载地址 https://dev.mysql.com/downloads/mysql/ 选择手动下载版本 mysql-5.7.25-winx64.zip 解压到自己指定的路径 上图中的 ...
- 5,临界区 之 lock
前提背景:多个并发线程共享同一个资源时,为防止这些共享资源可能出现的错误或数据不一致问题,提出了临界区的概念 临界区: 指一个用以访问共享资源的代码块,这个代码块在同一时间内只能允许一个线程访问 实现 ...
- wireshark的安装
wireshark是一款很强大的软件,我第一次接触是在计算机网络的课上,正是运用这款软件的时候. 下面我来介绍一下当初我安装时候的问题,方便大家的使用和参考 Wireshark(前称Ethereal) ...
- 正则表达式 python
下面这种方式 从结果上看 匹配的是关键字, 但是不是 每一次都可以 100% 准确 search_words_dict = { "肠炎宁": 0, "维生素AD" ...
- 虚拟立方体调用非共享维度的时候需要指定cubeName,否则Schema无效
但是,即使把非共享维度放上去,会出现一种情况. 一旦放入资产负债的非公共维度进去后,报表的度量值只能出现资产负债的度量值,不能出现损益的度量值了!
- MySql 的操作日志 历史记录
如何查看mysql数据库操作记录日志 1.首先确认你日志是否启用了mysql>show variables like 'log_bin'. 2.如果启用了,即ON,那日志文件就在mysql的安装 ...
- python全栈开发学习_day2_语言种类及变量
一.编程语言的分类及python相对其他语言的优势 1)三大语言种类及细分 1.机器语言(低级语言):直接用计算能够理解的二进制进行编写,直接控制计算机硬件. 优点:执行效率高. 缺点:开发效率低,跨 ...
- 2019年华南理工大学程序设计竞赛(春季赛) B 修仙时在做什么?有没有空?可以来炼丹吗?(思维建图搜索)
https://ac.nowcoder.com/acm/contest/625/B 分析: 全部的状态只有1<<18 个 , 所以我们可以预处理 f[u][j] , 然后建立出全部的u可以 ...
- [转] 基于Gitlab CI搭建持续集成环境
[From] https://blog.csdn.net/wGL3k77y9fR1k61T1aS/article/details/78798577 前言 本文是在12月12号迅雷@赵兵在前端早读课第三 ...
- webpack+vue解决前端跨域问题
webpack 跨域,在这里整理了一下逻辑首先不是为了axios库来进行跨域的,而是直接通过node的webpack设置代理来完成跨域的. 先贴一条自己请求的连接 1.设置自定义域: 在config目 ...