AOP的底层实现

 

 

一、Srping框架的AOP技术底层也是采用的代理技术,代理的方式提供了两种

二、代理模式

1、jdk动态代理

2、CGLIB字节码增强


一、Srping框架的AOP技术底层也是采用的代理技术,代理的方式提供了两种

    1. 基于JDK的动态代理

         必须是面向接口的,只有实现了具体接口的类才能生成代理对象

 

    2. 基于CGLIB动态代理

         对于没有实现了接口的类,也可以产生代理,产生这个类的子类的方式

 

2. Spring的传统AOP中根据类是否实现接口,来采用不同的代理方式

    1. 如果实现类接口,使用JDK动态代理完成AOP

    2. 如果没有实现接口,采用CGLIB动态代理完成AOP

二、代理模式

Proxy Pattern(即:代理模式),23种常用的面向对象软件的设计模式之一

代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

优点:

(1).职责清晰

真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。

(2).代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了的作用和保护了目标对象的作用。

(3).高扩展性

结构

一个是真正的你要访问的对象(目标类),另一个是代理对象,真正对象与代理

对象实现同一个接口,先访问代理类再访问真正要访问的对象。

代理模式简单案例

1、jdk动态代理

Java.lang.reflect.Proxy类可以直接生成一个代理对象

Proxy.newProxyInstance():产生代理类的实例。仅能代理实现至少一个接口的类

       ClassLoader:类加载器。固定写法,和被代理类使用相同的类加载器即可。

       Class[] interface:代理类要实现的接口。固定写法,和被代理类使用相同的接口即可。

       InvocationHandler:策略(方案)设计模式的应用。如何代理?

 

InvocationHandler中的invoke方法:调用代理类的任何方法,此方法都会执行   

         Object proxy:代理对象本身的引用。一般用不着。

         Method method:当前调用的方法。

         Object[] args:当前方法用到的参数

目标类接口:

public interface WorkInter {
	void workInDay(double money);
	void workInNight(double money);
}

目标类:

public class Worker implements WorkInter{

	@Override
	public void workInDay(double money) {
		System.out.println("workInDay");
		
	}
	@Override
	public void workInNight(double money) {
		System.out.println("workInNight");
	}
}

代理类:

public class JdkProxy {
	@Test
	public void run() {
		WorkInter proxy = (WorkInter) Proxy.newProxyInstance(Worker.class.getClassLoader(), Worker.class.getInterfaces(), new InvocationHandler() {
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

				System.out.println("中介费"+((double)args[0])/2);
				Object invoke = method.invoke(Worker.class.newInstance(), args);
				
				System.out.println("下班");
				return invoke;
			}
		});
		proxy.workInDay(500);
		proxy.workInNight(1000);
	}
}

执行结果:

2、CGLIB字节码增强

核心类:Enhancer

  1. 没有接口,只有实现类。
  2. 采用字节码增强框架 cglib,在运行时 创建目标类的子类,从而对目标类进行增强。

实现步骤:

  1. 获得代理类的核心类Enhancer对象
  2. 设置父类(目标类),setSuperclass()方法,底层是创建目标类的子类
  3. 设置回调函数enhancer.setCallback(new MethodInterceptor())
  4. 创建代理对象 create()方法

目标类:

public class Worker{
	public void workInDay(double money) {
		System.out.println("workInDay");
		
	}
	public void workInNight(double money) {
		System.out.println("workInNight");
	}
}

代理类:

public class WorkerProxy {
	@Test
	public void run() {
			Enhancer enhancer=new Enhancer();
			//2.设置父类(目标类),setSuperclass()方法,底层是创建目标类的子类
			enhancer.setSuperclass(Worker.class);
			//3.设置回调函数enhancer.setCallback(new MethodInterceptor()) 
			
			enhancer.setCallback(new MethodInterceptor() {
				    *//**
				 * Object object:代理对象
				 * Method method:目标类的方法
				 * Object[] args:方法的形参
				 * MethodProxy methodProxy:方法的代理对象
				 * 
				 *//*
				@Override
				public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
					// TODO Auto-generated method stub
					//开启事务
					//前置通知
					
					System.out.println("代理收取费用"+ (double)args[0]/2);
					//执行目标方法,需要目标类实例
					Object invoke = method.invoke(Worker.class.newInstance(), (double)args[0]/2);
					
					//后置通知
					
					System.out.println("go  home~~~~~");
					return invoke;
				}
			});
			
			//4.创建代理对象 create()方法
			Worker workerPeoxy = (Worker) enhancer.create();
			
			workerPeoxy.workInDay(500);
			workerPeoxy.workInNight(1000);
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章