Spring的AOP前置知识点(代理模式)

为什么要学习代理模式?因为这就是SpringAOP的底层! [SpringAOP 和SpringMVC]
代理模式的分类:
1.静态代理
2.动态代理

静态代理

角色分析:
1.抽象角色: 一般会使用接口或者抽象类来解决
2.真实角色:被代理的角色
3.代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
4.客户:访问代理对象的人!

代理模式的好处:
1.可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
2.公共也就就交给代理角色!实现了业务的分工!
3.公共业务发生扩展的时候,方便集中管理!
缺点:
1.一个真实角色就会产生一个代理角色;代码量会翻倍~开发效率会变低~

不改变原来的代码,生成额外的业务

动态代理

1.动态代理和静态代理角色一样
2.动态代理的代理类是动态生成的,不是我们直接写好的!
3.动态代理分为两大类:基于接口的动态代理,基于类的动态代理
(1)基于接口:JDK动态代理
(2)基于类:cglib
(3)java字节码实现 :javasist

需要了解两个类: Proxy: 代理,InvocationHandler: 调用处理程序
动态代理的好处:
1.可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
2.公共也就就交给代理角色!实现了业务的分工!
3.公共业务发生扩展的时候,方便集中管理!
4.一个动态代理类代理的是一个接口,一般就是对应的一类业务
5.一个动态代理类可以代理多个类,只要是实现了同一个接口即可

如何实现动态代理:

1、编写InvocationHandler动态代理类

(1)设置被代理的接口(target)

(2)利用Proxy.newProxyInstance(arg1,arg2,arg3)生成代理类proxy(参数arg1为类加载器,一般使用this.geClass.getClassLoading()通过反射获得,参数arg2为所要代理对象的接口,一般用target.getClass.getInterfaces()获取,参数arg3为InvocationHandler,可以直接用this)

(3)根据需求在invoke方法调用method.invoke(target,args)前后加入自己想要加入的增强方法

2、测试

(1)生成需要代理的类

(2)生成InvocationHandler动态代理类

(3)将需要代理的真实角色设置为target

(4)生成代理类Proxy

(5)Proxy调用方法

所用代码:

public interface UserService {
    void add();
    void delete();
    void update();
    void query();
}
public class UserServiceImpl implements UserService{
    public void add() {
        System.out.println("调用了add方法");
    }
    public void delete() {
        System.out.println("调用了delete方法");
    }
    public void update() {
        System.out.println("调用了update方法");
    }
    public void query() {
        System.out.println("调用了query方法");
    }
}
public class ProxyInvocationHandle implements InvocationHandler {
    private Object target;//被代理的接口
    public void setTarget(Object target) {
        this.target = target;
    }
    public Object getProxy(){//生成代理类
        return  Proxy.newProxyInstance(this.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//处理代理实例,并返回结果
        log(method.getName());//加入的增强方法,利用反射获取method名字
        Object result = method.invoke(target, args);
        return result;
    }
    public void log(String msg){
        System.out.println("执行了"+msg+"方法");
    }
}

测试代码

public class ProxyTest {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();//创建真实角色
        ProxyInvocationHandle handle = new ProxyInvocationHandle();//创建代理角色
        handle.setTarget(userService);//设置要代理的角色
        UserService proxy = (UserService) handle.getProxy();//动态生成代理类
        proxy.add();//调用方法
    }
}

测试结果:

猜你喜欢

转载自blog.csdn.net/qq_42500503/article/details/108944014