简介
代理分为两种,一种是静态代理,一种是动态代理。
静态代理:在编译的时候生成代理类的字节码;
动态代理:在程序运行的过程中生成代理类的字节码;
使用静态代理的时候,需要有个代理类和原来要加强的逻辑都有同样的接口,然后代理类通过实现接口来对想要操作的方法进行加强。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface IUserController {
UserVo login(String telephone, String password);
UserVo register(String telephone, String password);
}
public class UserController implements IUserController {
@Override
public UserVo login(String telephone, String password) {
//...省略逻辑...
}
@Override
public UserVo register(String telephone, String password) {
//...省略逻辑...
}
}
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
public class UserControllerProxy implements IUserController {
private static final Logger logger = LoggerFactory.getLogger(UserControllerProxy.class);
private UserController userController;
public UserControllerProxy(UserController userController) {
this.userController = userController;
}
@Override
public UserVo login(String telephone, String password) {
long startTime = System.currentTimeMillis();
UserVo userVo = userController.login(telephone, password);
long costTime = System.currentTimeMillis() - startTime;
logger.info("UserController#login cost time:" + costTime);
return userVo;
}
@Override
public UserVo register(String telephone, String password) {
long startTime = System.currentTimeMillis();
UserVo userVo = userController.register(telephone, password);
long costTime = System.currentTimeMillis() - startTime;
logger.info("UserController#register cost time:" + costTime);
return userVo;
}
}
JDK的动态代理
关键重点(其实就是通过反射把对应的类和方法加载到JVM,然后再通过反射来调用对应类的方法)
- 必须要求原始类是有接口定义才行。
- 实现InvocationHandler接口。
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
27
public class CtrlProxyHandler implements InvocationHandler {
private Object origBean;
public CtrlProxyHandler(Object origBean) {
this.origBean = origBean;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long startTime = System.currentTimeMillis();
Object res = method.invoke(origBean, args);
long costTime = System.currentTimeMillis() - startTime;
System.out.println(origBean.getClass().getSimpleName() + "#"
+ method.getName() + " cost time: " + costTime);
return res;
}
}
public class JDKProxyDemo {
public static void main(String[] args) {
IUserController userController = new UserController();
CtrlProxyHandler handler = new CtrlProxyHandler(userController);
IUserController userControllerProxy = (IUserController) Proxy.newProxyInstance(
handler.getClass().getClassLoader(), UserController.class.getInterfaces(), handler);
userControllerProxy.login("139********", "******");
}
}
CGLIB实现动态代理
关键点
- 需要引入cglib的包
- 实现MethodInterceptor接口
- 原始类是一个类,无需是接口
- Enhancer的使用