目前java动态代理的实现分为两种

  1. 基于JDK的动态代理(面向接口)
  2. 基于CGILB的动态代理(面向父类)

作用

在业务中使用动态代理,一般是为了给需要实现的方法添加预处理或者添加后续操作,但是不干预实现类的正常业务,把一些基本业务和主要的业务逻辑分离。我们一般所熟知的Spring的AOP原理就是基于动态代理实现的

基于JDK的动态代理

基于JDK的动态代理就需要知道两个类:1.InvocationHandler(接口)、2.Proxy(类)

第一步、创建一个接口

1
2
3
4
5
6
7
8
9
package dynamicProxy;

/**
* @author zhang
* @date 2020/12/22 17:36
*/
public interface Subject {
void hello(String param);
}

第二步、实现接口

1
2
3
4
5
6
7
8
9
10
11
12
package dynamicProxy;

/**
* @author zhang
* @date 2020/12/22 17:36
*/
public class SubjectImpl implements Subject{
@Override
public void hello(String param) {
System.out.println("Hello World");
}
}

第三步、创建SubjectImpl的代理类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package dynamicProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
* @author zhang
* @date 2020/12/22 17:37
* 创建SubjectImpl代理类
*/
public class SubjectProxy implements InvocationHandler {

private Subject subject;

public SubjectProxy(Subject subject){
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("--------begin-------");
//利用反射调用类里面的实际方法
Object invoke = method.invoke(subject, args);
System.out.println("---------end--------");
return invoke;
}
}

第四步、编写代理类的实际调用,利用Proxy类创建代理之后的Subject类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package dynamicProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
* @author zhang
* @date 2020/12/22 17:43
* 代理类实际调用
*/
public class Test {
public static void main(String[] args) {
Subject subject = new SubjectImpl();
InvocationHandler subjectProxy = new SubjectProxy(subject);

Subject subjectProxy1 = (Subject) Proxy.newProxyInstance(
subjectProxy.getClass().getClassLoader(),//代理类的类加载器
subject.getClass().getInterfaces(),//被代理的接口,如果有多个就是数组形式传入
subjectProxy//代理类的实例
);
subjectProxy1.hello("");
}
}

基于CGLIB的动态代理

因为基于JDK的动态代理一定要继承一个接口,而绝大部分情况是基于POJO类的动态代理,那么CGLIB就是一个很好的选择,在Hibernate框架中PO的字节码生产工作就是靠CGLIB来完成的。

引入CGLIB jar包

1
2
3
4
5
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>

创建代理类

1
2
3
4
5
6
7
8
9
10
11
package dynamicProxy;

/**
* @author zhang
* @date 2020/12/22 18:06
*/
public class CGSubject {
public void hello(String param){
System.out.println("hello" + param);
}
}

实现MethodInterceptor接口,对方法进行拦截

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package dynamicProxy;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
* @author zhang
* @date 2020/12/22 18:08
*/
public class HelloInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("----------begin---------");
Object object = methodProxy.invokeSuper(o, objects);
System.out.println("-----------end-----------");
return object;
}
}

创建被代理的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package dynamicProxy;

import net.sf.cglib.proxy.Enhancer;

/**
* @author zhang
* @date 2020/12/24 20:55
*/
public class CGTest {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(CGSubject.class);
enhancer.setCallback(new HelloInterceptor());
CGSubject cgSubject = (CGSubject) enhancer.create();
cgSubject.hello("zhangsan");
}
}

评论