AOP(一)底层原理代理方式(详解动态代理JDK、CGLIB)

AOP的代理方式主要分为两种,静态代理 和 动态代理。

在AspectJ 1.5 之后,引入了 @Aspect 形式的注解风格开发,Spring也非常快地跟进了这种方式,在Spring 2.0之后便使用了与Aspect 1.5 一样的注解。
注意:Spring只是使用了AspectJ的注解,而没有使用AspectJ的编译器,低层还是使用动态代理技术实现。

AspectJ使用静态代理
  静态代理的缺点很明显:
   一个代理类只能对一个业务接口的实现类进行包装,如果有多个业务接口的话,就要定义很多实现类进行代理才行。
   而且如果代理类对业务方法的预处理,调用后处理都是一样的(例如调用前输出提示,调用后关闭连接),则多个
   代理类就会有很多重复的代码。

Spring使用动态代理,主要有JDK实现和cglib实现。
	Spring创建代理的规则为:
	默认使用JDK动态代理来创建AOP代理
	当需要代理的类没有实现接口的时候,Spring会切换为使用cglib创建AOP代理
	可以在配置文件制定,强制使用cglib代理

Spring使用动态代理(详解)

JDK实现动态代理
   JDK动态代理的原理,是利用反射机制,生成一个和目标类继承了一样接口的匿名代理类。在调用具体方法
   前使InvocationHandler来处理。
   JDK动态代理的对象在创建时,需要使用业务实现类的接口作为参数(因为在后面代理方法时需要根据接口内的方
   法名进行调用)。
	如果业务实现类没有实现接口,就无法使用JDK动态代理了
	关键接口:java.lang.reflect.InvocationHandler
	关键类:java.lang.reflect.Proxy 和 java.lang.reflect.Method

  具体代码:
     //接口
	public interface  Jiekou {
	   void run();
	}
	
   //拓展类
	public class Jiekoushixian implements Jiekou {
		public void run() {
			System.out.println("接口实现了");
		}
	}
	
	//调用处理类invocationhandler
	import java.lang.reflect.InvocationHandler;
	import java.lang.reflect.Method;
	public class Diaoyongchuli implements InvocationHandler {
		private final Jiekou jiekou;
		public diaoyongchuli(Jiekou jiekou){
			this.jiekou = jiekou;
		}
		 //invoke三个参数:
		 //proxy:就是代理对象,newProxyInstance方法的返回对象
		 //method:调用的方法
		 //args: 方法中的参数
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			System.out.println("---------之前-------");
			Object invoke = method.invoke(jiekou, args);
			System.out.println("---------之后-------");
	 
			return invoke;
		}
	}
	//最终
	import java.lang.reflect.Proxy;
	public class App {
		public static void main(String[] args) {
			Jiekou jiekoushixian = new Jiekoushixian();
			//newProxyInstance,方法有三个参数:
			//loader: 用哪个类加载器去加载代理对象
			//interfaces:动态代理类需要实现的接口
			//h:动态代理方法在执行时,会调用h里面的invoke方法去执行
			Jiekou jiekou = (Jiekou)Proxy.newProxyInstance(jiekoushixian.getClass().
			 getClassLoader(), Jiekoushixian.class.getInterfaces(),
			 new Diaoyongchuli (jiekoushixian));
			//执行
			jiekou.run();
		}
cglib 动态代理
  cglib动态代理的原理是继承需要代理的类,生成的代理类是目标类的子类。
  用cglib生成的代理类重写了父类的各个方法。
  关键接口:org.springframework.cglib.proxy.MethodInterceptor
  关键类:org.springframework.cglib.proxy.Enhancer 和 
  org.springframework.cglib.proxy.MethodProxy

	public class CGlibDaili implements MethodInterceptor {

	   private Object proxyObject;

		public CGlibDaili(Object proxyObject) {
			this.proxyObject = proxyObject;
		}

		@Override
		public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
			System.out.println("---------之前-------");

			Object ret = method.invoke(proxyObject, objects);

			System.out.println("---------之后-------");
			return ret;
		}
	}

	// 工厂方法,获取代理对象
	public class ProxyFactory {
		public static Object createCGlibDailiInstance(Object proxyObject){
			Enhancer enhancer = new Enhancer();
			enhancer.setSuperclass(proxyObject.getClass());
			enhancer.setCallback(new CGlibDaili(proxyObject));
			return enhancer.create();
		}
		public static void main(String[] args) {
		Jiekoushixian jiekoushixian = new Jiekoushixian();
		Jiekoushixian jiekou=(Jiekoushixian)ProxyFactory.createCGlibDailiInstance(jiekoushixian);
		//执行
		jiekou.run();
		}
	}
两者的区别
	JDK 使用继承接口的方式生成代理类。(实现接口,管理代理实例)
	cglib 使用继承目标类的方式生成代理类。(生成目标类的子类,重写方法)
	JDK只能对继承了接口的类代理。
	cglib 除了 final 类都可以代理。
	JDK代理类生成快,但是运行效率较cglib代理差。
	cglib代理类生成慢,但是运行效率较JDK代理快。

Spring如何选择这两种代理
	目标对象实现了接口,默认使用JDK代理。
	目标对象实现了接口,可以选择强制使用 cglib 代理。
	目标对象没有实现接口,只能选择使用 cglib 代理。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值