目前我本人正在学习SpringFramework的知识,这也是这个专栏的主题。我前面的几篇博文中,简单的认识了一下SpringFramework,记录了SpringFramework的环境搭建,记录了SpringIOC如何加载配置文件,记录了SpringIOC三种Bean对象的实例化方法。还记录了SpringIOC手动装配(注入)的方法之一:set方法注入。还有另外三个不太常用的SpringIOC手动注入的方法。其实目前大部分都使用的是自动注入的方法,手动注入使用的不多。就算是使用手动注入的方法,使用的主流也是:set方法注入。自动注入的方法主要是使用两个注解,@Autowired注解或者是@Resource注解。两个注解我都记录到了。还记录了如何使用SpringIOC扫描器,SpringIOC中Bean对象的作用域和生命周期,SpringTask的概念和简单使用。本篇博客我记录一下SpringAOP的静态代理的概念和简单使用。
我的上一篇博文记录的是SpringTask的概念和简单使用,链接如下:
SpringTask定时任务的概念和简单使用_你是我的日月星河的博客-CSDN博客https://blog.csdn.net/weixin_46281472/article/details/125239290?spm=1001.2014.3001.5501
首先我粘贴一张图片,展示一下SpringAOP的学习方向,如下所示:
如上图所示,SpringAOP的代理模式分为两种,分别是静态代理和动态代理。其实我们工作中真正使用的比较多的是动态代理。动态代理呢,又分为JDK动态代理和CGLIB动态代理(这种需要引入第三方的依赖)。
首先我们先了解一下什么是代理模式:代理模式是JAVA开发中一种比较常见的设计模式;它的设计目的是 旨在为服务类和客户类之间插入其他功能,插入的功能对于调用者来说是透明的,起到伪装控制的作用;
打个比方吧:比如租房子,房客,中介,房东;对应于代理模式中也就是:客户类,代理类,委托类(被代理类)。
为某一个对象(委托类)提供一个代理(代理类),用来控制对这个对象的访问。委托类和代理类有一个共同的父类或者父接口;代理类会对请求做预处理,过滤,将请求分配给指定对象;
生活中类似代理的情况有很多啊:婚庆公司,租房中介,律师事务所;
代理模式有两个设计原则:
1、代理类 与 委托类 具有相似的行为(共同)
2、代理类增强委托类的行为;
常见的代理模式有:静态代理,动态代理;
先介绍一下静态代理:
为某一个对象提供一个代理,代理角色是固定的,是为了控制对这个角色的访问;代理类和委托类有共同的父类或者是父接口,这样在任何使用委托类对象的地方都可以使用代理对象替代;代理类负责请求的预处理,过滤,将请求分派给委托类处理,以及委托类执行完请求后的后续处理;
代理的三要素:有共同的行为(父接口,比如租房吧);目标角色(实现行为,比如有房子的人);代理角色(租房中介 也是实现行为,增强目标角色行为);
三要素可以理解为: 谁委托谁做什么事情;
静态代理的特点:
1、目标角色固定;可以说是委托类固定。
2、在应用程序执行前就得到目标角色;
3、代理对象会增强目标对象的行为;
4、有可能存在多个代理,引起“ 类爆炸” (缺点)(比如说吧,租房要有一个代理,结婚要有一个代理,租车要有一个代理 代理太多了)
静态代理其实真正使用的不多,真正使用的是动态代理。所以这里我就不做很复杂的代码实现了。
如上图所示,我们首先创建一个 RentHouse接口,这个接口就是我们的共同行为
共同行为RentHouse接口的代码如下:
package com.dcy.statics;
/*
这个是父类或者是父接口 也就是委托类和代理类共同的行为
*/
public interface RentHouse {
public void toRentHouse();
public String toRentHouse2(String name);
}
里面有两个方法,后面的代理类和委托类都需要继承实现这个接口。
然后就是我们的委托类(也就是想要出租房子的人) You,代码如下:
package com.dcy.statics;
/*
静态代理
下面这个是我们的 目标对象 也就是 委托类
*/
public class You implements RentHouse{
@Override
public void toRentHouse() {
System.out.println("我要租一个两室一厅");
}
@Override
public String toRentHouse2(String name) {
System.out.println(name+"要第二次租房");
return "好的吧";
}
}
很明显,上面的委托类继承实现了共同行为接口RentHouse。
然后就是我们的代理类(也就是租房中介)Agency,代码如下:
package com.dcy.statics;
/*
静态代理
这个是代理类 实现行为,还要增强目标对象的行为,
*/
public class Agency implements RentHouse{
private RentHouse target;
//下面我们需要提供一个有参构造,传递我们的目标对象
public Agency(RentHouse target) {
this.target = target;
}
@Override
public void toRentHouse() {
//下面这句话也是增强了行为
System.out.println("这里是中介");
target.toRentHouse();
System.out.println("准备合同");
}
@Override
public String toRentHouse2(String name) {
return null;
}
}
上面是代理类,类似于租房中介,代替房东行使一定的权力。既然是代理类,肯定和委托类是有相同的行为的,那么也是需要继承实现共同行为接口RentHouse的。既然是代理类,那么它究竟是谁的代理呢?为了体现它是谁的代理这一点,我们在代理类中加入了一个私有的成员变量,类型是RentHouse类型(共同行为接口),然后加入了一个有参构造,用来初始化这个私有成员变量。私有成员变量初始化以后,我们就可以在代理类的方法里面使用这个私有成员变量(也就是委托类对象,因为委托类对象实现了共同行为接口)的方法行为。
最后我们在Main方法里面进行一下简单的测试,代码如下所示:
package com.dcy.statics;
public class Starter {
public static void main(String[] args) {
You you=new You();
Agency agency=new Agency(you);
agency.toRentHouse();
}
}
运行结果如下所示:
我们需要明白的一点是:代理类最终调用的还是我们委托类中的方法;这一点是很容易从我上面简单的示例代码中看出来的。
如果我们的委托类有很多想要代理的事情,那么就需要有多个接口,有多个代理类;这明显是很麻烦的,也是静态代理的缺点,多以静态代理我们真正是不用的,用的是动态代理。
上述的例子是非常简单的例子,具体的使用肯定是很复杂的;
但是我们一般也是不使用静态代理的;
下一篇博文我介绍一下真正使用的动态代理,链接如下所示: