java动态代理和Cglib

JDK动态代理的原理是根据定义好的规则,用传入的接口创建一个新类,这就是为什么采用动态代理时为什么只能用接口引用指向代理,而不能用传入的类引用执行动态类。

cglib采用的是用创建一个继承实现类的子类,用asm库动态修改子类的代码来实现的,所以可以用传入的类引用执行代理类

动态代理

Java代码 复制代码
  1. package proxy.test;   
  2.   
  3. import java.lang.annotation.Retention;   
  4. import java.lang.annotation.RetentionPolicy;   
  5. import java.lang.reflect.InvocationHandler;   
  6. import java.lang.reflect.Method;   
  7. import java.lang.reflect.Proxy;   
  8.   
  9. /**  
  10.  * JAVA动态代理实现AOP  
  11.  *   
  12.  * from internet  
  13.  */  
  14. public class AopTest {   
  15.   
  16.     public static void main(String[] args) {   
  17.   
  18.         Before before = new Before() {   
  19.             public void before() {   
  20.                 System.out.println("...before...");   
  21.             }   
  22.         };   
  23.   
  24.         After after = new After() {   
  25.             public void after() {   
  26.                 System.out.println("...after...");   
  27.             }   
  28.         };   
  29.   
  30.         Hello hello = null;   
  31.   
  32.         // 普通方法执行   
  33.         System.out.println("-------------普通执行-------------");   
  34.         hello = new HelloEnglish();   
  35.         hello.sayHello("bao110908");   
  36.         hello.sayHi("bao110908");   
  37.         System.out.println();   
  38.   
  39.         // 切入方法执行前(前置增强)   
  40.         System.out.println("-------------前置增强-------------");   
  41.         hello = HelloAopManager.getHelloProxy(new HelloEnglish(), before);   
  42.         hello.sayHello("bao110908");   
  43.         hello.sayHi("bao110908"); // sayHi 方法没有标注 @Enhancement 所以不会进行代码切入   
  44.         System.out.println();   
  45.   
  46.         // 切入方法执行后(后置增强)   
  47.         System.out.println("-------------后置增强-------------");   
  48.         hello = HelloAopManager.getHelloProxy(new HelloEnglish(), after);   
  49.         hello.sayHello("bao110908");   
  50.         hello.sayHi("bao110908");   
  51.         System.out.println();   
  52.   
  53.         // 切入方法执行前和执行后(环绕增强)   
  54.         System.out.println("-------------环绕增强-------------");   
  55.         hello = HelloAopManager   
  56.                 .getHelloProxy(new HelloEnglish(), before, after);   
  57.         hello.sayHello("bao110908");   
  58.         hello.sayHi("bao110908");   
  59.         System.out.println();   
  60.     }   
  61. }   
  62.   
  63. @Retention(RetentionPolicy.RUNTIME)   
  64. @interface Enhancement {   
  65. }   
  66.   
  67. interface Hello {   
  68.     @Enhancement  
  69.     public void sayHello(String name);   
  70.   
  71.     public void sayHi(String name);   
  72. }   
  73.   
  74. class HelloChinese implements Hello {   
  75.     public void sayHello(String name) {   
  76.         System.out.println(name + ",您好");   
  77.     }   
  78.   
  79.     public void sayHi(String name) {   
  80.         System.out.println("哈啰," + name);   
  81.     }   
  82. }   
  83.   
  84. class HelloEnglish implements Hello {   
  85.     public void sayHello(String name) {   
  86.         System.out.println("Hello, " + name);   
  87.     }   
  88.   
  89.     public void sayHi(String name) {   
  90.         System.out.println("hi, " + name);   
  91.     }   
  92. }   
  93.   
  94. class HelloAopManager {   
  95.     private HelloAopManager() {   
  96.     }   
  97.   
  98.     public static Hello getHelloProxy(Hello hello, Before before) {   
  99.         return getHelloProxy(hello, before, null);   
  100.     }   
  101.   
  102.     public static Hello getHelloProxy(Hello hello, After after) {   
  103.         return getHelloProxy(hello, null, after);   
  104.     }   
  105.   
  106.     public static Hello getHelloProxy(Hello hello, Before before, After after) {   
  107.         HelloHandler handler = new HelloHandler();   
  108.         if (before != null) {   
  109.             handler.setBefore(before);   
  110.         }   
  111.         if (after != null) {   
  112.             handler.setAfter(after);   
  113.         }   
  114.         return handler.bind(hello);   
  115.     }   
  116. }   
  117.   
  118. /**  
  119.  * 前置增强接口  
  120.  */  
  121. interface Before {   
  122.     public void before();   
  123. }   
  124.   
  125. /**  
  126.  * 后置增强接口  
  127.  */  
  128. interface After {   
  129.     public void after();   
  130. }   
  131.   
  132. class HelloHandler implements InvocationHandler {   
  133.   
  134.     /**  
  135.      * 需要进行代理的实例  
  136.      */  
  137.     private Hello hello = null;   
  138.   
  139.     /**  
  140.      * 前置增强  
  141.      */  
  142.     private Before before = null;   
  143.   
  144.     /**  
  145.      * 后置增强  
  146.      */  
  147.     private After after = null;   
  148.   
  149.     /**  
  150.      * InvocationHandler 接口的实现方法,进行动态代理  
  151.      */  
  152.     public Object invoke(Object proxy, Method method, Object[] args)   
  153.             throws Throwable {   
  154.         // 看看接口中方法是否标注了需要 Enhancement   
  155.         boolean b = method.isAnnotationPresent(Enhancement.class);   
  156.         if (!b) {   
  157.             // 没有标注的话,按原方法执行   
  158.             return method.invoke(hello, args);   
  159.         }   
  160.         // 有标注的话,进行方法的前置和后置增强   
  161.         if (before != null) {   
  162.             before.before();   
  163.         }   
  164.         Object obj = method.invoke(hello, args);   
  165.         if (after != null) {   
  166.             after.after();   
  167.         }   
  168.         return obj;   
  169.     }   
  170.   
  171.     /**  
  172.      * 将传入的 Hello 与 InvocationHandler 进行绑定,以获得代理类的实例  
  173.      *   
  174.      * @param hello  
  175.      * @return  
  176.      */  
  177.     public Hello bind(Hello hello) {   
  178.         this.hello = hello;   
  179.         Hello helloProxy = (Hello) Proxy.newProxyInstance(hello.getClass()   
  180.                 .getClassLoader(), hello.getClass().getInterfaces(), this);// 这句用接口引用指向,不会报错。如果是实现类强制转换就会抛异常   
  181.         return helloProxy;   
  182.     }   
  183.   
  184.     public void setAfter(After after) {   
  185.         this.after = after;   
  186.     }   
  187.   
  188.     public void setBefore(Before before) {   
  189.         this.before = before;   
  190.     }   
  191. }  
package proxy.test;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * JAVA动态代理实现AOP
 * 
 * from internet
 */
public class AopTest {

	public static void main(String[] args) {

		Before before = new Before() {
			public void before() {
				System.out.println("...before...");
			}
		};

		After after = new After() {
			public void after() {
				System.out.println("...after...");
			}
		};

		Hello hello = null;

		// 普通方法执行
		System.out.println("-------------普通执行-------------");
		hello = new HelloEnglish();
		hello.sayHello("bao110908");
		hello.sayHi("bao110908");
		System.out.println();

		// 切入方法执行前(前置增强)
		System.out.println("-------------前置增强-------------");
		hello = HelloAopManager.getHelloProxy(new HelloEnglish(), before);
		hello.sayHello("bao110908");
		hello.sayHi("bao110908"); // sayHi 方法没有标注 @Enhancement 所以不会进行代码切入
		System.out.println();

		// 切入方法执行后(后置增强)
		System.out.println("-------------后置增强-------------");
		hello = HelloAopManager.getHelloProxy(new HelloEnglish(), after);
		hello.sayHello("bao110908");
		hello.sayHi("bao110908");
		System.out.println();

		// 切入方法执行前和执行后(环绕增强)
		System.out.println("-------------环绕增强-------------");
		hello = HelloAopManager
				.getHelloProxy(new HelloEnglish(), before, after);
		hello.sayHello("bao110908");
		hello.sayHi("bao110908");
		System.out.println();
	}
}

@Retention(RetentionPolicy.RUNTIME)
@interface Enhancement {
}

interface Hello {
	@Enhancement
	public void sayHello(String name);

	public void sayHi(String name);
}

class HelloChinese implements Hello {
	public void sayHello(String name) {
		System.out.println(name + ",您好");
	}

	public void sayHi(String name) {
		System.out.println("哈啰," + name);
	}
}

class HelloEnglish implements Hello {
	public void sayHello(String name) {
		System.out.println("Hello, " + name);
	}

	public void sayHi(String name) {
		System.out.println("hi, " + name);
	}
}

class HelloAopManager {
	private HelloAopManager() {
	}

	public static Hello getHelloProxy(Hello hello, Before before) {
		return getHelloProxy(hello, before, null);
	}

	public static Hello getHelloProxy(Hello hello, After after) {
		return getHelloProxy(hello, null, after);
	}

	public static Hello getHelloProxy(Hello hello, Before before, After after) {
		HelloHandler handler = new HelloHandler();
		if (before != null) {
			handler.setBefore(before);
		}
		if (after != null) {
			handler.setAfter(after);
		}
		return handler.bind(hello);
	}
}

/**
 * 前置增强接口
 */
interface Before {
	public void before();
}

/**
 * 后置增强接口
 */
interface After {
	public void after();
}

class HelloHandler implements InvocationHandler {

	/**
	 * 需要进行代理的实例
	 */
	private Hello hello = null;

	/**
	 * 前置增强
	 */
	private Before before = null;

	/**
	 * 后置增强
	 */
	private After after = null;

	/**
	 * InvocationHandler 接口的实现方法,进行动态代理
	 */
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		// 看看接口中方法是否标注了需要 Enhancement
		boolean b = method.isAnnotationPresent(Enhancement.class);
		if (!b) {
			// 没有标注的话,按原方法执行
			return method.invoke(hello, args);
		}
		// 有标注的话,进行方法的前置和后置增强
		if (before != null) {
			before.before();
		}
		Object obj = method.invoke(hello, args);
		if (after != null) {
			after.after();
		}
		return obj;
	}

	/**
	 * 将传入的 Hello 与 InvocationHandler 进行绑定,以获得代理类的实例
	 * 
	 * @param hello
	 * @return
	 */
	public Hello bind(Hello hello) {
		this.hello = hello;
		Hello helloProxy = (Hello) Proxy.newProxyInstance(hello.getClass()
				.getClassLoader(), hello.getClass().getInterfaces(), this);// 这句用接口引用指向,不会报错。如果是实现类强制转换就会抛异常
		return helloProxy;
	}

	public void setAfter(After after) {
		this.after = after;
	}

	public void setBefore(Before before) {
		this.before = before;
	}
}



CGLIB

Java代码 复制代码
  1. package proxy.test;   
  2.   
  3. import java.lang.reflect.Method;   
  4.   
  5. import net.sf.cglib.proxy.Enhancer;   
  6. import net.sf.cglib.proxy.MethodInterceptor;   
  7. import net.sf.cglib.proxy.MethodProxy;   
  8.   
  9. /**  
  10.  * 目标对象  
  11.  */  
  12. class Target {   
  13.   
  14.     public String execute() {   
  15.         String message = "----------test()----------";   
  16.         System.out.println(message);   
  17.         return message;   
  18.     }   
  19. }   
  20.   
  21. /**  
  22.  * 拦截器  
  23.  */  
  24. class MyMethodInterceptor implements MethodInterceptor {   
  25.   
  26.     public Object intercept(Object object, Method method, Object[] args,   
  27.             MethodProxy methodProxy) throws Throwable {   
  28.         System.out.println(">>>MethodInterceptor start...");   
  29.         Object result = methodProxy.invokeSuper(object, args);   
  30.         System.out.println(">>>MethodInterceptor ending...");   
  31.         return "here";   
  32.     }   
  33. }   
  34.   
  35. public class CglibTest {   
  36.     public static void main(String rags[]) {   
  37.         Target proxyTarget = (Target) createProxy(Target.class);// 强制转换为实现类,不会抛出异常   
  38.         String res = proxyTarget.execute();   
  39.         System.out.println(res);   
  40.     }   
  41.   
  42.     public static Object createProxy(Class targetClass) {   
  43.         Enhancer enhancer = new Enhancer();   
  44.         enhancer.setSuperclass(targetClass);   
  45.         enhancer.setCallback(new MyMethodInterceptor());   
  46.         return enhancer.create();   
  47.     }   
  48.   
  49. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值