Java的代理在各种框架中大放异彩, 我们也来大致唠唠.
代理的本质一句话总结, 对原函数的包装.
本质都说了, 那就不多xx了, 直接开始. show your code.
代理和java反射分不开, 这里有一篇” java 反射 “
静态代理
静态代理, 是我们主动进行编码, 没有其余辅助类库注入到我们的代码中.
写一个UserService接口, UserServiceImpl来实现这个接口, 然后我们在UserServiceProxy实现对于UserServiceImpl的代理.
public interface UserService {
void sayHello();
}
public class UserServiceImpl implements UserService {
@Override
public void sayHello() {
System.out.println("hello");
}
}
public class UserServiceProxy {
private UserService userService;
public UserServiceProxy(UserService userService) {
this.userService = userService;
}
public void sayHello() {
System.out.println("how are you?");
userService.sayHello();
System.out.println("goodbye~");
}
}
public static void main(String[] args) {
bootStaticProxy();
}
private static void bootStaticProxy(){
UserService service = new UserServiceImpl();
UserServiceProxy proxy = new UserServiceProxy(service);
proxy.sayHello();
}
当然, 也可以没有UserService这个接口, 直接代理指定的对象就行.
就是普通的代理模式, 没什么好说的.
JDK动态代理
要使用JDK进行动态代理, 会对代理类的代码有一定的侵入, 因为使用JDK进行动态代理, 要被代理的类必须实现要被代理的接口.
要代理的接口
public interface UserService {
void sayHello();
}
要被代理的类
public class UserServiceImpl implements UserService {
@Override
public void sayHello() {
System.out.println("hello");
}
}
实现代理的类
public class UserServiceProxyByJdk implements InvocationHandler {
private Object target;
public UserServiceProxyByJdk(Object target) {
this.target = target;
}
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
System.out.println("---begin " + method.getName());
Object result = method.invoke(target, objects);
System.out.println("---end " + method.getName());
return result;
}
public Object getProxy() {
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader()
, target.getClass().getInterfaces(), this);
}
}
getProxy()
方法可以写在生成代理对象逻辑中, 这是一个适配器, 方便调用.
private static void bootJdkProxy(){
UserService service = new UserServiceImpl();
UserServiceProxyByJdk userServiceProxyByJdk = new UserServiceProxyByJdk(service);
UserService userServiceProxy = (UserService) userServiceProxyByJdk.getProxy();
userServiceProxy.sayHello();
}
使用cglib进行动态代理
cglib 项目地址:https://github.com/cglib/cglib
cglib是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,cglib是一个好的选择。
cglib 原理: 动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。它比使用java反射的JDK动态代理要快。
cglib 底层: 使用字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。
cglib 无法对final方法进行代理
代理的方法的接口 (cglib不需要接口, 这个只是为了与上面统一, 可有可无)
public interface UserService {
void sayHello();
}
要被代理的类
public class UserServiceImpl implements UserService {
public void sayHello() {
System.out.println("hello");
}
}
实现代理
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz) {
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("how are you?");
Object result = methodProxy.invokeSuper(o, objects);
System.out.println("goodbye");
return result;
}
}
要实现cglib代理, 需要有类实现MethodInterceptor接口中的Intercept方法, 然后传入enhancer, 由enhancer负责代理对象的生成.