深入学习AOP笔记之:代理模式

1. 代理

AOP是面向切面编程的意思,而AOP底层用到的设计模式就是代理,要深入学习AOP就很有必要来了解一下代理设计模式。

场景 : 我们需要在一个业务实现类HelloImpl的hello()方法的前后分别执行before() 和 after的监控。

public interface Hello{
    public void say(String str);
}

public class HelloImpl implements Hello{
    public void say(String str){
         System.out.println("hello:"+ str);   
     }
}

有以下几种做法,每一种做法都是对前一种做法的提升。

1.1 写死代码
public class HelloImpl implements Hello{
    public void say(String str){
         before();
         System.out.println("hello:"+ str);   
         after();
     }

    private void before(){
         System.out.println("before hello");   
   }     
    private void after(){
         System.out.println("before hello");   
   }     
}

这种写死代码的缺点,就是与原有的业务代码耦合度高,需要动到原来的业务实现类的代码。

1.2 静态代理

保留原来的Hello接口和HelloImpl实现类,原封不动。 额外新增一个代理类HelloProxy来扩展额外的功能。

public class HelloProxy implements Hello{
    private Hello hello;
    public HelloProxy (){
           hello = new HelloImpl();   
     }
     private void before(){
         System.out.println("before hello");   
   }     
    private void after(){
         System.out.println("before hello");   
   }     
  
   @Overide
   public void say(String str){
         before();
         hello.say(str);
         after();
     }
}

这就是静态代理,对原来的业务接口实现类进行二次包装实现,从而达到对原始业务实现方法hello()的前后扩展。

缺点:试想一下,如果有100个这个的业务类需要扩展同样的包装,就需要新建100个对应的代理类,这样就造成了代理类数量的无限膨胀的问题。

1.3 动态代理:JDK动态代理

JDK动态代理是JDK使用动态反射机制为我们提供的一个动态代理的实现方法,可有效解决静态代理遗留的代理类数量的无限膨胀问题。

public class JDKDynamicProxy implements InvocationHandler{
    private Object target;//被代理的实现类
    
    public JDKDynamicProxy(Object target){
            this.target = target;
     }

    public <T> T getProxy(){
           return <T> Proxy.newProxyInstance(
               target.getClass().getClassLoader(),
               target.getClass().getInterfaces(),
               this
           );
     }

     @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
             before();
              Object result = method.invoke(target, args);
              after();
              return result;
       }

       private void before(){
         System.out.println("before hello");   
       }     
        private void after(){
             System.out.println("before hello");   
       }     
}
public class Client{

        public static void main(String[] args){
             Hello hello = new JDKDanamicProxy(new HelloImpl()).getProxy();
              hello.say("Jack");
         }
}

这样所有的代理类都合并到动态代理类中了,但这样子仍然存在一个问题:JDK给我提供的动态代理只能代理接口,而不能代理没有接口的类。有什么方法可以解决这个问题呢? 那就是CGLib动态代理。

1.4 动态代理:CGlib动态代理

CGLib动态代理是开源CGLib类库提供的动态代理机制,可以代理没有接口的类,有效弥补JDK动态代理的不足。

public class CGLibDynamicProxy implements MethodInterceptor{
    private static CGLibDynamicProxy instance = new CGLibDynamicProxy();
    
    private CGLibDynamicProxy(){}

    pubilc static CGLibDynamicProxy getInstance(){
            return instance;
     }
     
     @SuppressWarnings("unchecked")
     public <T> T getProxy(Class<T> cls){
            return (T) Enhancer.create(cls, this); 
      }
            
     @Override
      public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable{
            before();
            Object result = proxy.invokeSuper(target, args);
            after();
            return result;            
       }

       private void before(){
         System.out.println("before hello");   
       }     
        private void after(){
             System.out.println("before hello");   
       }     
}
public class Client{

    public static void main(String[] args){
            HelloImpl   hello = CGLibDynamicProxy.getInstance().getProxy(HelloImpl.class);
            hello.say("Jack");
     }
}

到此问题基本都解决了,以下图回顾总结一下: 输入图片说明

转载于:https://my.oschina.net/jackyli515/blog/1798746

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值