目录
代理模式:为一个对象提供一个替身,以控制对这个对象的访问。好处就是可以用来增强。
被代理的对象可以是 远程对象,创建开销大的对象 或者 需要安全控制的对象。
可以分为三类
示意图
目标对象与代理对象都要实现同一个接口或者继承相同父类。
代码实现:
- public interface ITeacherDao {
- String teach();
- }
-
-
- public class TeacherDao implements ITeacherDao{
- private String name;
- public TeacherDao(String name) {
- this.name = name;
- }
- @Override
- public String teach() {
- System.out.println(name + "老师正在讲课。。。");
- return name;
- }
- }
-
-
- public class TeacherDaoProxy implements ITeacherDao{
-
- private ITeacherDao teacherDao;
-
- public TeacherDaoProxy(ITeacherDao teacherDao) {
- this.teacherDao = teacherDao;
- }
-
- @Override
- public String teach() {
- System.out.println("开始静态代理。。。,可以进行增强");
- String name = teacherDao.teach();
- System.out.println("结束静态代理。。。");
- return name;
- }
- }
Client:
- public class Client {
- public static void main(String[] args) {
- ITeacherDao target = new TeacherDao("ksj");
-
- TeacherDaoProxy proxy = new TeacherDaoProxy(target);
-
- String teach = proxy.teach();
- System.out.println(teach);
- }
- }
静态代理缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类 ,一旦接口增加方法,目标对象与代理对象都要维护。
这就要用到动态代理了,动态的在内存中构建代理对象,只需要目标对象实现接口。利用JDK的Api来实现。
java.lang.reflect.Proxy里面的
newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h)
接口和目标类与上面静态代理相同,下面直接写代理工厂类
- public class ProxyFactory {
-
- private final 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("JDK代理开始");
- Object returnVal = method.invoke(target, args);
- System.out.println("JDK代理结束");
- return returnVal;
- }
- });
- }
- }
- public class Client {
- public static void main(String[] args) {
- ITeacherDao target = new TeacherDao("ksj");
- System.out.println("target=" + target.getClass());
- ProxyFactory proxyFactory = new ProxyFactory(target);
- ITeacherDao proxyInstance = (ITeacherDao) proxyFactory.getProxyInstance();
- // proxyInstance=class com.sun.proxy.$Proxy0 内存中动态生成了代理对象
- System.out.println("proxyInstance=" + proxyInstance.getClass());
- String name = proxyInstance.teach();
- System.out.println(name);
- }
- }
代码实现:
- public class TeacherDao {
- public String teach() {
- System.out.println(" 老师授课中 , 我是cglib代理,不需要实现接口 ");
- return "hello";
- }
- }
-
-
- public class ProxyFactory implements MethodInterceptor {
- //维护一个目标对象
- private Object target;
- //构造器,传入一个被代理的对象
- public ProxyFactory(Object target) {
- this.target = target;
- }
-
- //返回一个代理对象: 是 target 对象的代理对象
- public Object getProxyInstance() {
- //1. 创建一个工具类
- Enhancer enhancer = new Enhancer();
- //2. 设置父类
- enhancer.setSuperclass(target.getClass());
- //3. 设置回调函数
- enhancer.setCallback(this);
- //4. 创建子类对象,即代理对象
- return enhancer.create();
-
- }
-
- //重写 intercept 方法,会调用目标对象的方法
- @Override
- public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
- System.out.println("Cglib代理模式 ~~ 开始");
- Object returnVal = method.invoke(target, args);
- System.out.println("Cglib代理模式 ~~ 提交");
- return returnVal;
- }
- }
-
-
- public class Client {
-
- public static void main(String[] args) {
- //创建目标对象
- TeacherDao target = new TeacherDao();
- //获取到代理对象,并且将目标对象传递给代理对象
- TeacherDao proxyInstance = (TeacherDao)new ProxyFactory(target).getProxyInstance();
- //执行代理对象的方法,触发intecept 方法,从而实现 对目标对象的调用
- String res = proxyInstance.teach();
- System.out.println("res=" + res);
- }
- }
还有其他代理变体: