2023.02.17 星期五
1. 代理设计模式(Proxy)
1.1 什么叫代理
代理 就是 帮别人干活的人。
有些事情,本身是必须做的,但是我本人不想做。我就可以找个代理人帮我做。
1.2 什么叫代理设计模式
代理设计模式就是为当前对象,找一个代理对象,帮当前对象做一些其他的功能。
代理对象 就是 当前对象 功能的扩展。
1.3 代理模式的分类
现在代理设计模式有静态代理和动态代理二类
静态代理:编写一个代理类。实现对被代理类的功能的扩展。
动态代理:代理类是在程序运行过程,动态生成的类,实现对被代理类的功能的扩展。
1.4 使用继承实现功能扩展
/**
* 目标类。也称为被代理类
*/
public class A {
public void fun(){
System.out.println("A.fun()!!!");
}
}
/**
* 代理类,子类。
*/
public class ProxyA extends A{
@Override
public void fun() {
super.fun();
proxyFun();
}
public void proxyFun(){
System.out.println("ProxyA.proxyFun()!!");
}
}
public static void main(String[] args) {
A a = new ProxyA();
a.fun();
}
1.5 静态代理设计模式
1.5.1 编写代理接口
编写代理接口是用来暴露需要被代理的方法。
public interface Proxy {
void fun();
}
1.5.2 编写被代理类
编写被代理类
/**
* 目标类,被代理类
*/
public class Service implements Proxy {
@Override
public void fun() {
System.out.println("被代理的fun()");
}
}
1.5.3 编写代理类
静态代理模式是针对接口实现的代理。
1 与被代理类实现同一个代理接口(知道哪个方法需要被代理)
2 在代理类中编写代理接口的属性做为 被代理对象。
/**
* 代理类
*/
public class ProxyImpl implements Proxy {
private Proxy proxyTarget;//目标对象。被代理对象
public ProxyImpl(Proxy proxyTarget) {
this.proxyTarget = proxyTarget;
}
@Override
public void fun() {
System.out.println("功能之前的功能扩展!!!");
proxyTarget.fun();
System.out.println("功能之后的功能扩展!!!");
}
}
1.5.4 编写测试类
public static void main(String[] args) {
Service service = new Service();//被代理对象。
ProxyImpl proxyImpl = new ProxyImpl(service);//代理对象
proxyImpl.fun();
}
2 找切面(面向切面编程AOP)
2.1 切面
面向切面编程中,切面就是可以加入到源功能位置中的代码。
2.2 代理结构下哪些地方可以加切面
以我们已经学习过了try-catch异常处理之后。
每一行代码最完整的结构如下:
try{
}catch(Exception e){
}finally{
}
有一行代码加入到这个结构中时:
try{
//代码;
}catch(Exception e){
}finally{
}
参加代码的位置就是固定的4个:
try{
前();
//代码;
后();
}catch(Exception e){
异常();
}finally{
最终();
}
每一行代码,都只有4个地方可以加入切面代码。
2.3 编写切面接口
在这个接口,我们编写4个方法,分别对应4个位置。
public interface AOP {
void before();//前
void after();//后
void exception();//异常
void finall();//最终
}
2.4 修改代理类加入切面方法
public class ProxyImpl implements Proxy {
private Proxy proxyTarget;//目标对象。被代理对象
private AOP aop;//代理的内容
public ProxyImpl(Proxy proxyTarget, AOP aop) {
this.proxyTarget = proxyTarget;
this.aop = aop;
}
@Override
public void fun() {
try {
aop.before();
proxyTarget.fun();
aop.after();
}catch (Exception e){
e.printStackTrace();
aop.exception();
}finally{
aop.finall();
}
}
2.5 编写AOP的实现类
/**
* 事务切面的实现类
*/
public class TranAOPImpl implements AOP {
@Override
public void before() {
System.out.println("打开事务!");
}
public void after() {
System.out.println("提交事务!");
}
@Override
public void exception() {
System.out.println("回滚事务!");
}
@Override
public void finall() {
}
}
2.6 编写测试类
将 被代理对象 和 代理内容 都交给 代理对象
public static void main(String[] args) {
Service service = new Service();//被代理对象。
TranAOPImpl tranAOP = new TranAOPImpl();
ProxyImpl proxyImpl = new ProxyImpl(service,tranAOP);//代理对象
proxyImpl.fun();
}
3 IoC和DI
3.1 中文说明
IoC 控制反转
DI 依赖注入
3.2 分层结构
service 业务层
dao 数据访问层
service 依赖 dao。
IoC 控制反转
说的是,service获取dao对象的方式。
我们讨论的是serivce如何获得一个dao对象。
有如下版本的变化 :
3.3 第一版:主动获取
在Service类中使用new关键字。创建了一个依赖的DAO对象。
Service类使用哪一个DAO,是在Serivce类中自己说了算的。
public class DAO {
}
public class Service {
private DAO dao = new DAO();
}
问题:耦合度太高。
3.4 第二版:被动接收
降低耦合度。
1 删除new
2 创建接口
public interface DAO {
}
public class DAOImpl implements DAO {
}
看Service类
public class Service {
private DAO dao;
public void setDao(DAO dao) {
this.dao = dao;
}
}
现在Service使用哪一个DAO的实现类,Service自己说了算吗?不算。
IoC:控制反转。从原来的 主动获取 变成 现在的 被动接收。控制权发了改变。
public static void main(String[] args) {
Service service = new Service();
DAOImpl daoImpl = new DAOImpl();
service.setDao(daoImpl);//依赖注入
}
DI:依赖注入。外部通过 指定的方法 为Service类注入依赖关系对象。