1.静态代理
静态代理,顾名思义,手动代码代理。通过代理类实现被代理类的接口,进而完成代理过程。其实就是才能重写了,原本的接口方法,手动去在目标方法执行前中后,进行切割,进而实现代理。
public class TestStaticProxy {
public static void main(String[] args) {
IRegisterService iRegisterService = new RegisterServiceImpl();
IRegisterService proxy = new RegisterServiceProxy(iRegisterService);
proxy.register("RyanLee", "123");
}
}
interface IRegisterService {
void register(String name, String pwd);
}
class RegisterServiceImpl implements IRegisterService {
@Override
public void register(String name, String pwd) {
System.out.println(String.format("【向数据库中插入数据】name:%s,pwd:%s", name, pwd));
}
}
class RegisterServiceProxy implements IRegisterService {
IRegisterService iRegisterService;
public RegisterServiceProxy(IRegisterService iRegisterService) {
this.iRegisterService = iRegisterService;
}
@Override
public void register(String name, String pwd) {
System.out.println("[Proxy]一些前置处理");
System.out.println(“开始执行被代理的方法”);
iRegisterService.register(name, pwd);
System.out.println("[Proxy]一些后置处理");
}
}
2.JDK代理
JDK代理,动态代理类和被代理类必须继承同一个接口。动态代理只能对接口中声明的方法进行代理,有一定限制。每一个动态代理实例都有一个关联的InvocationHandler。通过代理实例调用方法,方法调用请求会被转发给InvocationHandler的invoke方法。(这里就可以看出为啥在实例化代理类时,要传入目标类的接口,这样在代理类实现的invoke方法里可以直接执行接口方法实现了目标类被代理的过程)。实际上我们发现JDK的动态代理是基于反射的,而实现方式和静态代理很像,那为啥又说是动态代理呢?其实,细心的小伙伴就已经发现,JDK动态代理这种方式是一种对目标方法的增强,他不关心你目标方法,而是通过newProxyInstance方法来生成新的 的代理对象,只管代理执行,此处解耦。而对比静态代理就需要静态代理类知道目标类的信息,实现目标类的接口,限制很多。而动态代理在实现代理的时候,是传递需要代理类,的实现,无关接口 所以并不需要为每一种接口都写一个代理类了。
public static void main(String[] args) {
Target tar = new Target();
ProxyHandler handler = new ProxyHandler();
BBQ proxy = (BBQ) handler.getProxy(tar);
proxy.sayBBQ("LF");
}
static class Target implements BBQ {
@Override
public void sayBBQ(String s) {
System.out.println("这是原方法执行的 say bbq " + s);
}
}
interface BBQ {
void sayBBQ(String s);
}
static class ProxyHandler implements InvocationHandler {
Object obj;
public Object getProxy(Object obj) {
this.obj = obj;
Object o = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
return o;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
doBefore();
Object result = method.invoke(obj, args);
doAfter();
return result;
}
private void doBefore() {
Thread thread = Thread.currentThread();
System.out.println("[Proxy]一些前置处理" + thread.getName() + " " + thread.getId());
}
private void doAfter() {
System.out.println("[Proxy]一些后置处理");
}
}
3.cglib代理
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
public static void main(String[] args) {
Target tar = new Target();
CGLIBProxyDemo handler = new CGLIBProxyDemo();
Target proxy = (Target) handler.getProxy(tar);
proxy.sayBBQ("cglib代理");
}
static class Target implements JDKProxyUtil.BBQ {
@Override
public void sayBBQ(String s) {
System.out.println("这是原方法执行的 say bbq " + s);
}
}
interface BBQ {
void sayBBQ(String s);
}
static class CGLIBProxyDemo implements MethodInterceptor {
private Object target;
public Object getProxy(Object obj) {
this.target = obj;
Enhancer enhancer = new Enhancer();
//生成子类
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] param, MethodProxy methodProxy) throws Throwable {
doBefore();
Object result = methodProxy.invokeSuper(obj, param);
doAfter();
return result;
}
private void doBefore() {
Thread thread = Thread.currentThread();
System.out.println("[Proxy]一些前置处理" + thread.getName() + " " + thread.getId());
}
private void doAfter() {
System.out.println("[Proxy]一些后置处理");
}
}
结语
仔细观察会发现:的原理依据,就是多态,要么实现接口生成代理类,要么继承目标类生成代理类,而的手段就是反射,利用反射来获取被代理类的信息,进而才能实现不需要了解目标信息来构建多态,从而动态解耦。
网友评论