1. 代理模式(Proxy)
一种设计模式,提供了对对象的另一种访问方式,即通过代理对象访问目标对象。好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。(不修改目标对象)
代理对象是对目标对象的扩展,并会调用目标对象。
1.1 静态代理
静态代理在使用时,需要定义接口或者父类,被代理的对象与代理对象一起实现相同的接口,或者继承相同的父类。
public interface IUserDao {
void save();
}
public class UserDaoImpl implements IUserDao {
@Override
public void save() {
System.out.println("--------- save data ---------");
}
}
public class UserDaoProxy implements IUserDao {
private IUserDao target;
public UserDaoProxy (IUserDao target) {
this.target = target;
}
@Override
public void save() {
System.out.println("--------- begin ---------");
target.save();
System.out.println("--------- end ---------");
}
}
public class TestStaticProxy {
public static void main(String[] args) {
IUserDao target = new UserDaoImpl();
UserDaoProxy proxy = new UserDaoProxy(target);
proxy.save();
}
}
1.2 动态代理(JDK代理,接口代理)
特点:
① 代理对象不需要实现接口
② 代理对象的生成是利用JDK的API,动态的在内存中构建代理对象(需要指定代理对象/目
标对象实现的接口类型)
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
InvocationHandler: 事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把目标对象的方法作为参数传入。
public class ProxyFactory {
/**
* 维护一个目标对象
*/
private Object target;
public ProxyFactory (Object target) {
this.target = target;
}
/**
* 给目标对象生成代理对象
*/
public Object getProxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("====== start ======");
Object result = method.invoke(target, args);
System.out.println("====== end ======");
return result;
}
});
}
}
代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理。
1.3 cglib代理(子类代理)
以目标对象子类的方式实现代理。在内存中构建一个子类对象从而实现对目标对象功能的扩展。
目标对象如果是final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法
在spring的aop编程中,如果加入容器的目标对象有实现接口,用JDK代理。如果目标对象没有实现接口,用cglib代理。
public class ProxyFactory implements MethodInterceptor {
/**
* 维护目标对象
*/
private Object target;
public ProxyFactory (Object target) {
this.target = target;
}
/**
* 给目标对象维护一个代理对象
* @return
*/
public Object getProxyInstance() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("--------- start ---------");
Object result = method.invoke(target, objects);
System.out.println("--------- end ---------");
return result;
}
}
public class TestCglib {
public static void main(String[] args) {
IUserDao userDao = new UserDaoImpl();
IUserDao proxy =
(IUserDao) new ProxyFactory(userDao).getProxyInstance();
proxy.save();
}
}