java代理

代理

概念

         代理模式是对象的结构型模式,代码模式给某一个对象提供代理,并由代理对象控制原对象(目标对象,被代理对象)的引用。简单点说,就是通过一个工厂生成一个类的代理对象,当客户端使用的时候不直接使用目标对象,而是直接使用代理对象。代理对象相当于中介.

1        Jdk静态代理

1.1     概念

1.1.1     代理类和目标类实现相同的接口

1.1.2     代理类持有目标类的     的引用

1.2      实例

1.2.1     创建接口

public interface UserService {  

    public void addUser(String userId,String userName);  

}  

1.2.2     创建实现类

public class UserServiceImpl implements UserService {

    @Override

    public void addUser(String userId, String userName) {

       System.out.println("UserServiceImpl addUser userId->>"+userId);

    }

}

1.2.3     创建代理类

(代理类持有被代理类的引用)

public class UserServiceImplProxy implements UserService {

    private UserService userService;

    public UserServiceImplProxy(UserService userService){

       this.userService = userService;

    }

    @Override

    public void addUser(String userId, String userName) {

       try {

           System.out.println("开始执行:addUser");

           userService.addUser(userId, userName);

           System.out.println("addUser执行成功。");

       } catch (Exception e) {

           System.out.println("addUser执行失败。");

       }

    }

         }

1.2.4     创建测试类

public class Client {

         public static void main(String[] args) {

          UserService userService = new UserServiceImplProxy(new UserServiceImpl());

          userService.addUser("001", "centre");

         }

}

1.2.5     缺点

需要为每一个目标类创建一个代理类,需要建立大量的代理类,耦合度高.违背了重复代码只写一次的原则.

 

 

2        Jdk动态代理

2.1     概念

Jdk的动态要求目标对象必须实现接口,因为它创建代理对象的时候是根据接口创建的。如果不实现接口,jdk无法给目标对象创建代理对象。被代理对象可以可以实现多个接口,创建代理时指定创建某个接口的代理对象就可以调用该接口定义的方法了   

2.1.1     被代理对象必须实现接口,可以实现多个接口

2.1.2     代理对象由代理工厂生成

2.2     实例

2.2.1   创建接口Service接口和UserService接口(上面的接口)

public interface Service {

      public void sayHello(String name);

}

 

2.2.2     创建目标对象

public class UserServiceImpl implements UserService ,Service{

         @Override

         public void addUser(String userId, String userName) {

                   System.out.println("UserServiceImpl addUser userId->>"+userId);

         }

@Override

         public void sayHello(String name) {

                   System.out.println("你好:"+name);

         }

              }

2.2.3     创建生成代理对象的类

 

public class LogHandler implements InvocationHandler {

         private Object targertObject;

         public Object newInstance(Object targertObject){

                   this.targertObject = targertObject;

                   Class targertClass = targertObject.getClass();

                return  Proxy.newProxyInstance(targertClass.getClassLoader(),

targertClass.getInterfaces(),this);

         }

  @Override

         public Object invoke(Object proxy, Method method, Object[] args)

                            throws Throwable {

                   System.out.println("调用方法"+method.getName());

                   Object ret = null;

                   try {

                            ret = method.invoke(targertObject, args);

                            System.out.print("成功调用方法:"+method.getName()+";参数为:");

                            for (int i = 0; i < args.length; i++) {

                                     System.out.println(args[i]);

                            }

                   } catch (Exception e) {

                            e.printStackTrace();

                            System.out.print("调用方法:"+method.getName()+"失败;参数为:");

                            for (int i = 0; i < args.length; i++) {

                                     System.out.print(args[i]);

                            }

                   }

                   return ret;

         }

}

2.2.4     创建测试类

public class Client {

         public static void main(String[] args) {

                   Service Service = (Service)new LogHandler().newInstance(new UserServiceImpl());

                   UserService userService = (UserService)new LogHandler().newInstance(new UserServiceImpl());

                   userService.addUser("001", "centre");

                   Service.sayHello("centre");

         }

}

2.2.5     缺点

jdk给目标类提供动态要求目标类必须实现接口,当一个目标类不实现接口时,jdk是无法为其提供动态代理的

3        Jdk动态代理

3.1     CGLIB动态代理

spring在给某个类提供动态代理时会自动在jdk动态代理和cglib动态代理中动态的选择。使用cglib为目标类提供动态代理:需要导入cglib.jar和asm.jar

如果出现asm中的类无法找到的异常,在java工程中是真的缺少asm.jar,而在web工程中很可能是asm.jar和spring提供的org.springframework.asm-3.0.4.RELEASE.jar包冲突。

3.1.1    CGLIB动态代理首先编写一个目标类:UserServiceImpl.java(上面的类)

3.1.2    然后为其创建一个代理工厂,用于生成目标类的代理对象:CglibProxy.java

如果一个类继承了某个类,在子类中没有一个方法,用cglib生成该子类的动态代理类中将没有一个方法。

3.1.3     编写CGLIB代理类

public class CglibProxy implements MethodInterceptor{

 

         @Override

         public Object intercept(Object obj, Method method, Object[] args,

                            MethodProxy proxy) throws Throwable {

        System.out.println("调用的方法是:" + method.getName());

        Object ret = null;

        try {

            ret = proxy.invokeSuper(obj, args);

                            System.out.print("成功调用方法:"+method.getName()+";参数为:");

                            for (int i = 0; i < args.length; i++) {

                                     System.out.print(args[i]);

                            }

                   } catch (Exception e) {

                            e.printStackTrace();

                            System.out.print("调用方法:"+method.getName()+"失败;参数为:");

                            for (int i = 0; i < args.length; i++) {

                                     System.out.print(args[i]);

                            }

                   }

                   return ret;

         }

}

3.1.4     编写测试类

public class CglibClient {

         public static void main(String[] args) {

                   cglibUse1();

         }

         public static void cglibUse1(){

                   Enhancer enhancer = new Enhancer();

 

                   // 设置被代理的类(目标类)

                   enhancer.setSuperclass(UserServiceImpl.class);

                   //使用回调

                   enhancer.setCallback(new CglibProxy());

 

                   // 创造 代理 (动态扩展了UserServiceImpl类)

                   UserServiceImpl my = (UserServiceImpl) enhancer.create();

 

                   //my.addUser("001", "centre");

                   int ret = my.addOperter(15, 22);

                   System.out.println("返回的结果是:"+ret);

         }

}

4         jdk动态和cglib动态代理比较

Jdk动态代理要求被代理的类要实现接口,而cglib不需要,cglib能根据内存中为其创建子类(代理对象)

5        个人理解

Jdk静态代理可以理解为中介(代理类)知道一切,所有的事情由中介来处理,其他的类完成自己的功能就好了.

jdk动态代理以接口作为媒介,利用反射建立起代理类和被代理类的关系.

CGLib的具体还有点没有理解,希望可以有人补充.

 

摘自: http://blog.csdn.net/centre10/article/details/6847828

转载于:https://my.oschina.net/u/2615530/blog/761714

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java代理模式是一种结构型设计模式,其目的是为其他对象提供一种代理以控制对这个对象的访问。代理对象可以在客户端和目标对象之间充当中介,以便于客户端访问目标对象时,可以在不改变目标对象的情况下添加一些额外的功能,比如安全性、远程访问、缓存等。 在Java中,代理模式可以通过两种方式实现:静态代理和动态代理。静态代理需要手动编写代理类,而动态代理可以在运行时通过反射机制动态生成代理类,更加灵活。 举个例子,假设我们有一个接口`Subject`,其中定义了一些方法。我们希望在调用这些方法时,增加一些额外的日志记录功能。我们可以编写一个代理类`SubjectProxy`,在代理类中实现接口方法并调用目标对象的方法,同时在方法前后添加日志记录的代码。客户端则通过代理类访问目标对象。 静态代理示例代码如下: ```java public interface Subject { void doSomething(); } public class RealSubject implements Subject { @Override public void doSomething() { System.out.println("RealSubject do something."); } } public class SubjectProxy implements Subject { private Subject realSubject; public SubjectProxy(Subject realSubject) { this.realSubject = realSubject; } @Override public void doSomething() { System.out.println("Before do something."); realSubject.doSomething(); System.out.println("After do something."); } } public class Client { public static void main(String[] args) { Subject realSubject = new RealSubject(); Subject subjectProxy = new SubjectProxy(realSubject); subjectProxy.doSomething(); } } ``` 动态代理示例代码如下: ```java public class SubjectHandler implements InvocationHandler { private Object target; public SubjectHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before " + method.getName()); Object result = method.invoke(target, args); System.out.println("After " + method.getName()); return result; } } public class Client { public static void main(String[] args) { Subject realSubject = new RealSubject(); InvocationHandler handler = new SubjectHandler(realSubject); Subject subjectProxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler); subjectProxy.doSomething(); } } ``` 无论是静态代理还是动态代理代理模式都可以在不改变目标对象的情况下,为其添加额外的功能,提高代码的可复用性和灵活性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值