一、静态代理
根据被代理的类的时机的不同,如果在编译阶段就能确定下来的被代理的类是哪一个,那么,就可以使用静态代理的方式。
申明一个接口:
1 /** 2 * @author [email protected] 3 * @version 1.0 4 * @name 5 * @description 6 * @date 2018/7/23 7 */ 8 public interface Person { 9 void sayHello(String content, int age); 10 }
实现类,即需要被代理的类:
1 /** 2 * @author [email protected] 3 * @version 1.0 4 * @name 5 * @description 需要被代理的类 实现接口 6 * @date 2018/7/23 7 */ 8 public class Student implements Person { 9 @Override 10 public void sayHello(String content, int age) { 11 System.out.println("student say hello " + content + " "+ age); 12 } 13 }
实现类:
1 /** 2 * @author [email protected] 3 * @version 1.0 4 * @name 5 * @description 6 * @date 2018/7/23 7 */ 8 public class StaticProxyTest implements Person{ 9 //接口对象 10 private Person o; 11 12 public StaticProxyTest(Person o){ 13 this.o = o; 14 } 15 16 public static void main(String[] args) { 17 // TODO Auto-generated method stub 18 //s为被代理的对象,某些情况下 我们不希望修改已有的代码,我们采用代理来间接访问 19 //在代理类中引入被代理的对象 20 Student s = new Student(); 21 //创建代理类对象 s是接口的实例 22 StaticProxyTest proxy = new StaticProxyTest(s); 23 //调用代理类对象的方法 24 proxy.sayHello("welcome to java", 20); 25 } 26 27 @Override 28 public void sayHello(String content, int age) { 29 // TODO Auto-generated method stub 30 System.out.println("ProxyTest sayHello begin"); 31 //在代理类的方法中 间接访问被代理对象的方法 32 o.sayHello(content, age); 33 System.out.println("ProxyTest sayHello end"); 34 } 35 }
二、动态代理
如果不能在代码的编译阶段就去确定需要代理的类是哪一个的话,就可以使用类的动态代理机制,在代码运行期间去动态加载类的信息。
Java动态代理和Cglib方式的代理的重要区别:
Java动态代理只能对接口进行代理,如果要代理的类是一个普通的类,没有接口则需要使用Cglib来实现。
Java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
Cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
创建接口:
1 /** 2 * @author [email protected] 3 * @version 1.0 4 * @name 5 * @description 6 * @date 2018/7/23 7 */ 8 public interface IStudent { 9 void action(); 10 }
1 /** 2 * @author [email protected] 3 * @version 1.0 4 * @name 5 * @description 6 * @date 2018/7/23 7 */ 8 public class StudentImpl implements IStudent{ 9 @Override 10 public void action() { 11 System.out.println("Student action"); 12 } 13 }
基于jdk的动态代理 该动态代理一定要实现InvocationHandler
1 /** 2 * @author [email protected] 3 * @version 1.0 4 * @name 5 * @description 基于jdk的动态代理 该动态代理一定要实现InvocationHandler 6 * @date 2018/7/23 7 */ 8 public class JavaProxy implements InvocationHandler { 9 private Object target; 10 11 /** 12 * 绑定委托对象并返回一个代理类 13 * 14 * @param target 15 * @return 16 */ 17 public Object bind(Object target) { 18 this.target = target; 19 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); // 要绑定接口 20 } 21 22 @Override 23 public Object invoke(Object proxy, Method method, Object[] args) 24 throws Throwable { 25 Object result; 26 //在这里可以做拦截前的操作 27 System.out.println("【java代理】调用实际方法前"); 28 // 执行方法 29 result = method.invoke(target, args); 30 //在这里可以做拦截后的操作 31 System.out.println("【java代理】调用实际方法后"); 32 return result; 33 } 34 }
1 /** 2 * @author [email protected] 3 * @version 1.0 4 * @name 5 * @description 6 * @date 2018/7/23 7 */ 8 public class TestProxy { 9 public static void main(String[] args) { 10 //创建代理对象 11 JavaProxy proxy = new JavaProxy(); 12 //绑定接口对象 13 IStudent student = (IStudent) proxy.bind(new StudentImpl()); 14 //调用接口方法 15 student.action(); 16 } 17 }
三、基于cglib的动态代理
可以对任何的普通类进行代理
1 /** 2 * @author [email protected] 3 * @version 1.0 4 * @name 5 * @description 一个普通类 6 * @date 2018/7/23 7 */ 8 public class StudentImpl { 9 public void action() { 10 System.out.println("[Student]实际方法。。。"); 11 } 12 }
代理类要去实现MethosInterceptor接口:
1 /** 2 * @author [email protected] 3 * @version 1.0 4 * @name 5 * @description 6 * @date 2018/7/23 7 */ 8 public class CgLibProxy implements MethodInterceptor { 9 private Object target; 10 11 /** 12 * 创建代理对象 13 * 14 * @param target 15 * @return 16 */ 17 public Object getInstance(Object target) { 18 this.target = target; 19 Enhancer enhancer = new Enhancer(); 20 enhancer.setSuperclass(this.target.getClass()); 21 // 回调方法 22 enhancer.setCallback(this); 23 // 创建代理对象 24 return enhancer.create(); 25 } 26 27 // 回调方法 拦截方法 在调用具体的业务逻辑前和后 进行其他的相关处理 28 @Override 29 public Object intercept(Object obj, Method method, Object[] args, 30 MethodProxy proxy) throws Throwable { 31 System.out.println("[cglib代理]调用实际方法前"); 32 proxy.invokeSuper(obj, args); 33 System.out.println("[cglib代理]调用实际方法后"); 34 return null; 35 } 36 }
1 /** 2 * @author [email protected] 3 * @version 1.0 4 * @name 5 * @description 6 * @date 2018/7/23 7 */ 8 public class TestProxy { 9 public static void main(String[] args) { 10 CgLibProxy cglib = new CgLibProxy(); 11 StudentImpl student = (StudentImpl) cglib.getInstance(new StudentImpl()); 12 student.action(); 13 } 14 }