SpringAOP 对象代理笔记

Spring AOP笔记:

应用场景: 日志记录,异常的统一处理,权限验证,事务处理。
 
什么是叫做面向切面编程。
Aop是什么?-----------编程需要实现的目标,实现面向切面编程
SpringAOP是什么?-----实现这个目标的手段
 
AOP的两种实现形式:
  • SpringAOP
  • Aspectj

切面(Aspect):

其实就是共有功能的实现。如日志切面、权限切面、事务切面等。在实际应用中通常是一个存放共有功能实现的普通Java类,之所以能被AOP容器识别成切面,是在配置中指定的。

在自上而下的执行的业务逻辑过程中,会产生一些横切性的问题,比如说日志记录,异常的统一处理,权限验证,事务处理等,与主业务逻辑没有直接的关系

面向切面的思想就是把这些横切性的问题模块化成为一个切面,程序员只需关注切面的执行顺序,执行时机即可。

Java动态代理(代理模式/委托模式)

1、代理的定义

为其他对象提供一种代理以控制对这个对象的访问。

代理模式

代理模式是面向对象编程中比较常见的设计模式

代理模式( Proxy Pattern ): 一个类代表另一个类的功能,一般用于对要访问的类做一些控制、功能增强,同时又不想影响原来类的正常业务;
需要注意的有下面几点:
 
用户只关心接口功能,而不在乎谁提供了功能。上图中接口是 Subject。
接口真正实现者是上图的 RealSubject,但是它不与用户直接接触,而是通过代理。
代理就是上图中的 Proxy,由于它实现了 Subject 接口,所以它能够直接与用户接触。
用户调用 Proxy 的时候,Proxy 内部调用了 RealSubject。所以,Proxy 是中介者,它可以增强 RealSubject 操作
 
现在可以看到, 代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。
值得注意的是,代理类和被代理类应该共同实现一个接口,或者是共同继承某个类。
Java动态代理(代理模式/委托模式)
 
1、代理的定义
 
为其他对象提供一种代理以控制对这个对象的访问。
 
 

代理模式

代理模式是面向对象编程中比较常见的设计模式。
代理模式( Proxy Pattern ): 一个类代表另一个类的功能,一般用于对要访问的类做一些控制、功能增强,同时又不想影响原来类的正常业务;
需要注意的有下面几点:
 
用户只关心接口功能,而不在乎谁提供了功能。上图中接口是 Subject。
接口真正实现者是上图的 RealSubject,但是它不与用户直接接触,而是通过代理。
代理就是上图中的 Proxy,由于它实现了 Subject 接口,所以它能够直接与用户接触。
用户调用 Proxy 的时候,Proxy 内部调用了 RealSubject。所以,Proxy 是中介者,它可以增强 RealSubject 操作
 
现在可以看到, 代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。
值得注意的是,代理类和被代理类应该共同实现一个接口,或者是共同继承某个类。
 
 
2、代理的使用场景
 
在某些情况下,我们不希望或是不能直接访问对象 A,而是通过访问一个中介对象 B,由 B 去访问 A 达成目的,这种方式我们就称为代理。
 
这里对象 A 所属类我们称为委托类,也称为被代理类,对象 B 所属类称为代理类。
 
代理优点有:
  • 隐藏委托类的实现
  • 解耦,不改变委托类代码情况下做一些额外处理,比如添加初始判断及其他公共操作
根据程序运行前代理类是否已经存在,可以将代理分为静态代理和动态代理。
3)静态代理和动态代理
动态代理静态代理的区别,代理涉及到两个关联词代理类和委托类。静态代理一个代理类针对一个委托类!动态代理一个代理类可利用反射机制代理多个委托类
eg:经纪人是代理类,明星是委托类。静态代理是经纪人A服务一个明星,而动态代理是经纪人A服务多个明星。
我们根据加载被代理类的时机不同,将代理分为静态代理和动态代理。如果我们在代码编译时就确定了被代理的类是哪一个,那么就可以直接使用静态代理;如果不能确定,那么可以使用类的动态加载机制,在代码运行期间加载被代理的类这就是动态代理,比如RPC框架和Spring AOP机制。
(4)静态代理
优点:可以实现不对目标对象进行修改的前提下,对目标对象进行功能的扩展和增强,也就是扩展原功能, 不污染原代码。
缺点:因为代理对象,需要实现与目标对象一样的接口,如果目标接口类繁多也会导致代理类繁多,同时一旦接口增加方法,则目标对象和代理类都需要维护。
我们先创建一个接口, 遗憾的是java api代理机制求被代理类必须要实现某个接口,对于静态代理方式代理类也要实现和被代理类相同的接口 ;对于动态代理代理类则不需要显示的实现被代理类所实现的接口。
 
1.创建一个代理类和委托类的公有父级接口
package com.ztb.staticDL;
public interface TargetClass {
    void sayHello();
}

 

2.创建一个委托类(也就是目标类)

package com.ztb.staticDL;

public class TargetImpl implements TargetClass {

    @Override
    public void sayHello() {
        System.out.println("静态代理,打印SayHello方法");
    }
}

3.创建代理类(代理类是为了加强目标类的功能)

package com.ztb.staticDL;

public class ProxyClass implements TargetClass{
    private  TargetImpl target;//持有一个代理目标对象的引用
     //eg:让黄牛代理买票你得让黄牛知道你的个人信息

    public ProxyClass(TargetImpl target) {
        this.target = target;//目标类也就是代理类需要初始化一下。不然会报空指针异常
    }
    @Override
    public void sayHello() {
        //调用目标类的方法,同时可以增强目标类的方法
        System.out.println("代理方法前");
        target.sayHello();//
        System.out.println("代理方法后");
    }
}

3.测试(用户调用)

package com.ztb.staticDL;


import com.sun.xml.internal.bind.v2.util.StackRecorder;


public class Client {


    public static void main(String[] args) {


//        TargetImpl target=new TargetImpl();
//        target.sayHello();//传统方法调用目标对象的方法

        ProxyClass proxyClass=new ProxyClass(new TargetImpl());
        proxyClass.sayHello();//通过代理类调用目标对象的方法
    }
}

4.测试结果截图

(5)动态代理(三要素:目标接口,目标接口实现,实现  InvocationHandler的类)

1、代理对象是由谁产生的?
jvm产生的,不像上次的静态代理,我们自己得new个代理对象出来。
2、代理对象实现了什么接口?
实现的接口是目标对象实现的接口。同静态代理模式中代理对象实现的接口。那个继承关系图还是相同的。代理对象和目标对象都实现一个共同的接口。就是这个接口。所以Proxy.newProxyInstance()方法返回的类型就是这个接口类型。
3、代理对象的方法体是什么?
代理对象的方法体中的内容就是拦截器中invoke方法中的内容 。所有代理对象的处理逻辑,控制是否执行目标对象的目标方法。都是在这个方法里面处理的。
4、拦截器中的invoke方法中的method参数是在什么时候赋值的?
在客户端,代理对象调用目标方法的时候,此实例中为:proxyObj.business();
实际上进入的是拦截器中的invoke方法,这个时候 ,拦截器中的invoke方法中的method参数会被赋值。

最后,为啥这个方式叫做jdk动态代理呢?

因为这个动态代理对象时用jdk的相关代码生成的,所以这个叫jdk动态代理。

后面的cglib动态代理,就是因为要用到cglib的jar包,所以才叫cglib动态代理。

简易实现动态代理的例子:

1.先给出接口

package com.ztb.dynamicProxy;
public interface TargetClass {
    void sayHello();
}

2.定义委托类(也就是目标类),实现接口

package com.ztb.dynamicProxy;


public class TargetImpl implements TargetClass {
    @Override
    public void sayHello() {
        System.out.println("动态代理,打印SayHello方法");


    }
}

3..定义协助实现代理类的辅助类

package com.ztb.dynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
* ProxyClass这个类不是代理类,而是辅助真正的代理类去工作。。
* 是动态代理的一部分
*/
public class ProxyClass implements InvocationHandler {

    private Object  target;//传入目标对象引用

    public ProxyClass(Object target) {
        this.target = target;
    }

    /**
     * 在调用目标类的sayHello()方法时,会先调用invoke()方法。
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 

        System.out.println("目标方法执行前。。。。。。");

        Object result=method.invoke(target,args);//在这里真正调用sayHello()方法
        //result 是目标方法的返回值

        System.out.println("目标方法执行后。。。。。。");
        return result;
    }
}

4.编写测试类

package com.ztb.dynamicProxy;

import java.lang.reflect.Proxy;
public class Client2 {

    public static void main(String[] args) {
//
//        TargetImpl target=new TargetImpl();
//        target.sayHello();

/**
** targetClass才是正真的代理类.通过Proxy.newProxyInstance()方法强转得到的。
*/
      TargetClass targetClass= (TargetClass)Proxy.newProxyInstance(TargetClass.class.getClassLoader(),
                new Class[] {TargetClass.class},new ProxyClass(new TargetImpl()) );
        targetClass.sayHello();
    }
}

5.运行结果。

动态代理语法

放轻松,下面我们开始讲解语法,语法非常简单。
动态代码涉及了一个非常重要的类 Proxy。正是通过 Proxy 的静态方法 newProxyInstance 才会动态创建代理。
public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
loader 自然是类加载器
interfaces 代码要用来代理的接口
h 一个 InvocationHandler 对象

InvocationHandler

InvocationHandler 是一个接口 ,官方文档解释说,每个代理的实例都有一个与之关联的 InvocationHandler 实现类,如果代理的方法被调用,那么代理便会通知和转发给内部的 InvocationHandler 实现类,由它决定处理。
 
public interface InvocationHandler {
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; 
}

InvocationHandler 内部只是一个 invoke() 方法,正是这个方法决定了怎么样处理代理传递过来的方法调用。
proxy 代理对象
method 代理对象调用的方法
args 调用的方法中的参数

总结:

代理分为静态代理和动态代理两种。
静态代理,代理类需要自己编写代码写成。
动态代理,代理类通过 Proxy.newInstance() 方法生成
不管是静态代理还是动态代理,代理与被代理者都要实现两样接口,它们的实质是面向接口编程。
静态代理和动态代理的区别是在于要不要开发者自己定义 Proxy 类。
动态代理通过 Proxy 动态生成 proxy class,但是它也指定了一个 InvocationHandler 的实现类。
代理模式本质上的目的是为了增强现有代码的功能。
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值