动态代理
静态代理确实可以做到解耦,但是由于业务增强的代码(日志,权限校验等)写的相对固定,灵活性较差,如果在业务量较大的情况下,需要程序员手动的去写大量的相同的代码,这就是静态代理的弊端。
如果将这些增强业务的代码集中写到一个代理类中,将来有任何的相关的业务需求,都可以通过这个代理类来实现。
动态代理有两种:
JDK动态代理:要求必须有接口,最终生成的代理类和目标类实现相同的接口,在com.sun.proxy包下。
cglib动态代理:最终生成的代理类会继承目标类,并且和目标类在相同的包下。
JDK动态代理
首先创建一个目标类的接口Calculator:
public interface Calculator {
int add(int a,int b);
}
目标类:CalculatorImpl
public class CalculatorImpl implements Calculator{
@Override
public int add(int a, int b) {
return a+b;
}
}
创建ProxyFactory类:
该类是为了生产代理类而创建的工厂类,通过该类中的getProxy()方法可以产出代理类
public class ProxyFactory {
//目标类对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
//通过该方法来产出代理类
public Object getProxy()
{
/**
* ClassLoader loader;类加载器,将生成的代理类加载到内存
* 三种类加载器:
* 根类加载器:主要是加载核心类库,底层是由C来实现的
* 扩展类加载器:主要加载的是扩展类库
* 应用类加载器:加载第三方类库和自定义类
* Class[] interfaces:目标类实现的接口
* InvocationHandler:设置代理类如何实现目标类接口所定义的方法
*/
//获取应用类加载器
ClassLoader classLoader = this.getClass().getClassLoader();
//获得目标类实现的接口
Class<?>[] interfaces = target.getClass().getInterfaces();
InvocationHandler h=new InvocationHandler() {
//invoke表示代理类中的方法的执行
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//proxy表示代理类对象,method表示要执行的方法,args表示要执行的方法的参数列表
System.out.println("要增强的业务代码。。。。");
//在代理类中执行目标类的方法
Object result = method.invoke(target, args);
System.out.println("要增强的业务代码。。。。。");
return result;
}
};
return Proxy.newProxyInstance(classLoader,interfaces,h);
}
}
测试:
public class TestJDKProxy {
public static void main(String[] args) {
ProxyFactory proxyFactory=new ProxyFactory(new CalculatorImpl());
Calculator proxy = (Calculator)proxyFactory.getProxy();
int add = proxy.add(1, 2);
System.out.println(add);
}
}