一、静态代理
根据被代理的类的时机的不同,如果在编译阶段就能确定下来的被代理的类是哪一个,那么,就可以使用静态代理的方式。
申明一个接口:
1 /**
2 * @author jiaqing.xu@hand-china.com
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 jiaqing.xu@hand-china.com
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 jiaqing.xu@hand-china.com
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 jiaqing.xu@hand-china.com
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 jiaqing.xu@hand-china.com
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 jiaqing.xu@hand-china.com
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 jiaqing.xu@hand-china.com
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 jiaqing.xu@hand-china.com
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 jiaqing.xu@hand-china.com
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 jiaqing.xu@hand-china.com
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 }