原创声明:本博客来源为本人原创作品,绝非他处摘取,转摘请联系博主

代理(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代理原理-代理使用浅析的更多相关文章

  1. 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。

    基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...

  2. Spring -- <tx:annotation-driven>注解基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)的区别。

    借鉴:http://jinnianshilongnian.iteye.com/blog/1508018 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional ...

  3. Spring <tx:annotation-driven>注解 JDK动态代理和CGLIB动态代理 区别。

    基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...

  4. spring AOP底层原理实现——jdk动态代理

    spring AOP底层原理实现——jdk动态代理

  5. spring源码学习【准备】之jdk动态代理和cglib动态代理的区别和性能

    一:区别:---->JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了.--->JDK的动态代理机制只能代理实现了接口的类,而不能 ...

  6. JDK动态代理和CGLIB代理的区别

    一.原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 而cglib动态代理是利用asm开源包,对代理对象类的class文件 ...

  7. Spring AOP实现原理-动态代理

    目录 代理模式 静态代理 动态代理 代理模式 我们知道,Spring AOP的主要作用就是不通过修改源代码的方式.将非核心功能代码织入来实现对方法的增强.那么Spring AOP的底层如何实现对方法的 ...

  8. jdk动态代理和cglib动态代理的区别

    一.原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 而cglib动态代理是利用asm开源包,对代理对象类的class文件 ...

  9. java的静态代理、jdk动态代理和cglib动态代理

    Java的代理就是客户端不再直接和委托类打交道,而是通过一个中间层来访问,这个中间层就是代理.使用代理有两个好处,一是可以隐藏委托类的实现:二是可以实现客户与委托类之间的解耦,在不修改委托类代码的情况 ...

  10. jdk 动态代理和 cglib 动态代理

    原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 而cglib动态代理是利用asm开源包,对代理对象类的class文件加载 ...

随机推荐

  1. 全局CSS的配置

    /*公共部分开始*/ ::selection{ background-color: #3095fb; color: white; } ::moz-selection{ background-color ...

  2. Win10通电自动开机的解决办法

    前几天Win10强推系统升级,更新后无意中发现每次通电电脑就自动开机了. 解决办法: 打开控制面板>电源选项>选择电源按钮的功能,把关机设置里的“启用快速启动(推荐)”选项去掉就可以了. ...

  3. 从零开始完整搭建 Spring-Boot 项目开发框架的教程

    前言 难度:简单 类型:step-by-step 适用:初学者,完全没有接触过 Spring-Boot 开发环境:jdk 1.8 关键词:java, sring-boot, spring-mvc, r ...

  4. 使用范围for语句处理多维数组

    在C++11新标准中新增了范围for语句,所以遍历多维数组可以用如下形式: int num[rowCnt][colCnt]; for(auto &row : num){ for(auto &a ...

  5. [转] java获取hostIp和hostName

    [From] https://www.cnblogs.com/huluyisheng/p/6867370.html InetAddress的构造函数不是公开的(public),所以需要通过它提供的静态 ...

  6. appium解决无法通过name属性识别元素org.openqa.selenium.InvalidSelectorException: Locator Strategy 'name' is not supported for this session

    执行代码.: public AndroidDriver<AndroidElement> appiumDriver; appiumDriver.findElement(By.name(&qu ...

  7. 20190430-screen、client、offset、scroll等JS中各种宽度距离

    参考文献: JavaScript概念之screen/client/offset/scroll/inner/avail的width/left

  8. Windows操作系统的发展简介

    一.简介    Microsoft Windows,是美国微软公司研发的一套操作系统,它问世于1985年,起初仅仅是Microsoft-DOS模拟环境,后续的系统版本由于微软不断的更新升级,不但易用, ...

  9. RabbitMQ---初识

    1.概述 1.1 RabbitMQ   是  实现了   高级消息队列协议(AMQP) 的开源   消息代理软件,也称为  面向消息的中间件: AMQP:Advanced Message Queuin ...

  10. sql server取某个时间段内所有日期或者所有月份

    取所有月份: declare @begin datetime,@end datetime set @begin='2015-2-6' set @end='2015-12-2' declare @mon ...