SpringAOP、静态代理、动态代理(重要)

一、静态代理

  • 以示例介绍源头对象通过中间代理对象进行一些必要的审核筛选最后还是目标对象最终确认

1、定义:为目标对象提供一种代理以控制这个对象的访问,在不改变目标对象的行为的前提下,对目标对象行为的增强

Client1:客户端

RealSubject:目标对象

Proxy:代理对象,通常具有以下功能(秘书)

1、实现与具体的目标对象一样的接口,这样就可以是使用代理来代替具体的目标对象。(外界访问时候秘书也具有董事长相同功能)

2、保存一个具体的目标对象引用,可以在需要的时候调用具体的目标对象的方法。

3、可以控制对具体目标对象的访问。权限控制、日志处理。

让目标对象和代理类实现同一个接口,目的是让客户端访问的时候代理对象和目标对象表现行为是一致。这其实就是一种保护(对目标对象的保护),控制对具体目标对象的访问,这个时候就由代理说了算。

在代理对象里面转调目标对象之前和之后做一些事(打印日志、权限控制等),

这样就方便为原有的功能添加新的功能,这就是代理模式。

举例

//Client-------客户端
public class Client {
    public static void main(String[] args) {
    DongShiZhang dongShiZhang = new DongShiZhang();
    MiShu miShu = new MiShu(dongShiZhang);
    miShu.qianzi();
        }
    }
//dongshizhang 
//目标对象
public class DongShiZhang implements IQianzi{

    @Override
    public void qianzi() {
        System.out.println("DongShiZhang.qianzi");
    }
}
//mishu
//代理对象Proxy
//董事长日理万机,客户不能直接和董事长打交道,董事长身边的人有秘书和司机,
//让董事长和秘书都实现IQianzi这个接口,让他们对外都具备签字这个行为,
//客户只要把文件交给秘书就可以,当然可以也知道秘书只是前期审核后期收尾处理,
//真正签字的还是董事长,但是还是要交给秘书,因为只有秘书实现了对外签字这个行为,司机肯定没有。
public class MiShu implements IQianzi{
        //代理对象里面要引用目标对象,代理对象不能真正完成签字,目标对象才可以
    private DongShiZhang dongShiZhang;

    public MiShu(DongShiZhang dongShiZhang){
        this.dongShiZhang=dongShiZhang;
    }
    @Override
    public void qianzi() {
     //代理模式能实现调用目标对象之前或者之后加上一些额外的功能
        System.out.println("开启事务");
        System.out.println("MiShu.qianzi 前期处理");
        dongShiZhang.qianzi();
        System.out.println("MiShu.qianzi 后期收尾");
        System.out.println("关闭事务");
    }
}
//qianzi
//让目标对象和代理类实现同一个接口,目的是让客户端访问的时候行为是一致。
public interface IQianzi {
    void qianzi();
}
MiShu.qianzi before 开始事物
MiShu.qianzi 前期审核
DongShiZhang.qianzi
MiShu.qianzi 后期收尾
MiShu.qianzi after 关闭事物

执行的结果

静态代理缺点

  • 有一个目标就有一个代理有多个目标就有多个代理会产生太多的代理类类太多
  • 接口新增一个方法目标代理对象都要修改维护

静态代理优点

  • 可以做到不修改目标对象的前提下,对目标对象的功能进行扩展
  • (目标对象董事长只要关注签字,像开启事物和关闭事物的操作都交给秘书处理)

二、动态代理

动态代理(JDK代理):

  1. 不需要自己写代理类,但是目标对象还是需要实现接口;
  2. 代理对象的生成,是利用JDK API, 动态的在内存中构建代理对象
  3. 动态代理也叫:JDK代理,接口代理;

JDK中生成代理对象的API:

|-- Proxy java.lang.reflect.Proxy

static Object newProxyInstance(

ClassLoader loader, 指定当前目标对象使用类加载器

Class[] interfaces, 目标对象实现的接口的类型

InvocationHandler h 事件处理器

)

给我任何一个目标对象(目标对象必须要实现一个接口),动态代理会生成一个代理对象。

public class ProxyFactory {

    /**
     * 给我任何一个目标对象(目标对象不许要实现一个接口),动态呆逼会生成一个代理对象
     * @param target
     * @return 代理对象
     */
    public static Object getProxyInstance(Object target) {
        return Proxy.newProxyInstance(
                //目标对象的类加载器
                target.getClass().getClassLoader(),
                //目标对象实现的接口
                target.getClass().getInterfaces(),
                //匿名内部类(接口不能new,只能写一个实现类,实现接口中的方法),  可以称为事件处理器
                //Object proxy 代理对象
                //Method method 调用的方法
                //Object[] args 调用方法的参数
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object o, Method method, Object[] args) throws Throwable {
                        System.out.println(target.getClass().getName()+"."+method.getName());
                        System.out.println("开启事务");
                        method.invoke(target,args);
                        System.out.println("关闭事务");
                        return null;
                    }
                }
        );
    }
}

 @Test
    public void tes1() {
        DongShiZhang dongShiZhang = new DongShiZhang();
        IQianzi proxy = (IQianzi) ProxyFactory.getProxyInstance(dongShiZhang);
        proxy.qianzi();
    }
    
//结果:
com.situ.spring.proxy.DongShiZhang.qianzi
开启事务
DongShiZhang.qianzi
关闭事务

 @Test
    public void tes2() {
        IStudentService studentService = new StudentServiceImpl();
        IStudentService proxy = (IStudentService) ProxyFactory.getProxyInstance(studentService);
        proxy.selectAll();
    }
//结果
com.situ.spring.service.impl.StudentServiceImpl.selectAll
开启事务
StudentServiceImpl.selectAll
关闭事务

动态代理的优点和缺点:

优点:不需要自己去创建代理类。

缺点:但是目标对象一定要实现接口,否则不能用动态代理。

三、Cglib代理了解)

也叫做子类代理,在内存中构建一个子类对象从而实现对目标对象功能的扩展。

JDK的动态代理有一个限制,使用动态代理的对象必须实现一个或多个接口。如果想代理不实现接口,就可以使用CGLIB实现。

Cglib代理要求:目标对象不能为final, 否则报错。

目标对象的方法如果为final/static, 那么就不会被拦截,即不会执行目标对象额外的业务方法。

在Spring的AOP编程中:

如果加入容器的目标对象有实现接口,用动态代理(JDK代理);

如果目标对象没有实现接口,用Cglib代理;

四、AOP

1AOPAspect Oriented Programming面向切面编程

功能让关注点代码(事务、权限、日志要增强的功能)业务代码分离

2、拦截器、过滤器都是基于代理模式思想

Object Oriented Programming面向对象编程 OOP

3事物:逻辑上的一组操作,保证要么同时成功,要么同时失败(失败之后会回滚)

例子:A给B转账

设计到两条sql语句,一个是A账户减100,另一个是B账户加100,这个过程卸在Service层,

所以在Service层都会加上事物

public void transfer(A a, B b, double money) {

// 开启事物 (要增强的功能,也就是关注点代码)

调用dao代码:a-100;

调用dao代码:b+100;

// 关闭事物(要增强的功能,也就是关注点代码)

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值