小小千想和您聊一聊

当前位置: 首页> 技术分享> Spring框架之AOP原理动态代理

Spring框架之AOP原理动态代理

  前言

  动态代理是一种常用的设计模式,广泛应用于框架中,Spring框架的AOP特性就是应用动态代理实现的,想要理解AOP的实现原理我们就必须先理解动态代理。

  什么是代理模式

  代理模式是GOF23设计模式之一,代理模式中存在代理者和被代理者,代理者和被代理者都具有相同的功能,并且代理者执行功能时会附加一些额外的操作

  如:手机工厂和代理商都具有卖东西的功能,手机代理商除了帮工厂卖手机外,还能在卖手机前打广告推销,卖手机后还可以进行售后服务。

  代理模式的优点:

  1)符合开闭原则,不用修改被代理者任何的代码,就能扩展新的功能

  2)项目的扩展和维护比较方便

  代理模式分为:静态代理和动态代理

  静态代理

  什么是静态代理

  1)代理者和被代理者都实现了相同的接口(或继承相同的父类)

  2)代理者包含了一个被代理者的对象

  3)调用功能时,代理者会调用被代理者的功能,同时附加新的操作

1.	/**
2.	 * 卖手机
3.	 */
4.	public interface SellMobilePhone {
5.	
6.	    void sellMobilePhone();
7.	}
8.	/**
9.	 * 小米手机工厂
10.	 */
11.	public class MiPhoneFactory implements SellMobilePhone{
12.	
13.	    public void sellMobilePhone() {
14.	        System.out.println("生产了小米9手机,卖出去!!");
15.	    }
16.	}
17.	/**
18.	 * 小米代理商
19.	 */
20.	public class MiPhoneAgent implements SellMobilePhone {
21.	
22.	    //被代理者,工厂对象
23.	    private SellMobilePhone factory;
24.	
25.	    //通过构造方法传入被代理者
26.	    public MiPhoneAgent(SellMobilePhone factory){
27.	        this.factory = factory;
28.	    }
29.	
30.	    public void sellMobilePhone() {
31.	        System.out.println("打广告,做活动~~~~~~~~~~~~~~~~~");
32.	        //调用被代理者的方法
33.	        factory.sellMobilePhone();
34.	        System.out.println("做售后,做推销~~~~~~~~~~~~~~~~~");
35.	    }
36.	}
37.	public class TestStaticProxy {
38.	
39.	    @Test
40.	    public void testProxy(){
41.	        //创建被代理者
42.	        SellMobilePhone factory = new MiPhoneFactory();
43.	        factory.sellMobilePhone();
44.	        System.out.println("---------------------------------------");
45.	        //创建代理者
46.	        SellMobilePhone agent = new MiPhoneAgent(factory);
47.	        //调用卖手机
48.	        agent.sellMobilePhone();
49.	    }
50.	}

  静态代理的问题:

  静态代理只能适合一种业务,如果有新的业务,就必须创建新的接口和新的代理,如添加卖电脑的接口和电脑工厂,就要创建新的电脑代理类。

  动态代理

  动态代理的特点:

  1) 在不修改原有类的基础上,为原来类添加新的功能

  2) 不需要依赖某个具体业务

  动态代理分为:JDK动态代理和CGLib动态代理

  区别是:

  JDK动态代理的被代理者必须实现任意接口

  CGLib动态代理不用实现接口,是通过继承实现的

  JDK动态代理

  实现步骤:

  1)代理类需要实现InvocationHandler接口

  2)实现invoke方法

  3)通过Proxy类的newProxyInstance方法来创建代理对象

1.	/**
2.	 * 动态代理
3.	 */
4.	public class SalesAgent implements InvocationHandler{
5.	
6.	    //被代理者对象
7.	    private Object object;
8.	
9.	    /**
10.	     * 创建代理对象
11.	     * @param object 被代理者
12.	     * @return 代理者
13.	     */
14.	    public Object createProxy(Object object){
15.	        this.object = object;
16.	        //Proxy.newProxyInstance创建动态代理的对象,传入被代理对象的类加载器,接口,InvocationHandler对象
17.	        return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
18.	    }
19.	
20.	    /**
21.	     * 调用被代理者方法,同时添加新功能
22.	     */
23.	    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
24.	        System.out.println("销售之前,打广告~~~~~~");
25.	        //调用被代理者的方法
26.	        Object result = method.invoke(object,args);
27.	        System.out.println("销售之后,做售后~~~~~~");
28.	        return result;
29.	    }
30.	}
31.	public class TestInvocationHandler {
32.	
33.	    @Test
34.	    public void testInvocation(){
35.	        //创建动态代理对象
36.	        SalesAgent agent = new SalesAgent();
37.	        //被代理对象
38.	        SellMobilePhone sellMobilePhone = new MiPhoneFactory();
39.	        //创建代理对象
40.	 SellMobilePhone phoneProxy = (SellMobilePhone) agent.createProxy(sellMobilePhone);
41.	        phoneProxy.sellMobilePhone();
42.	    }
43.	}

  CGLib动态代理

  特点:通过继承实现,被代理者必须能被继承,通过被代理类创建子类,子类就是父类的代理。

1.	/**
2.	 * CGLib动态代理
3.	 *
4.	 */
5.	public class CGLibProxy implements MethodInterceptor {
6.	
7.	    /**
8.	     * 返回代理对象
9.	     * @param object 被代理对象
10.	     * @return 代理对象
11.	     */
12.	    public Object createProxy(Object object){
13.	        //创建加强器
14.	        Enhancer eh = new Enhancer();
15.	        //设置被代理对象的类为父类
16.	        eh.setSuperclass(object.getClass());
17.	        //设置代理对象的回调
18.	        eh.setCallback(this);
19.	        return eh.create();
20.	    }
21.	
22.	    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
23.	        System.out.println("售前~~~~~~CGLIB");
24.	        //调用父类对象的方法
25.	        Object res = proxy.invokeSuper(obj, args);
26.	        System.out.println("售后~~~~~~CGLIB");
27.	        return res;
28.	    }
29.	}

  总结

  代理模式分为静态代理和动态代理,静态代理只能代理某一种业务,动态代理可以代理各种业务而不用添加新的代理类,动态代理分为JDK动态代理和CGLib动态代理,JDK动态代理类必须实现某个接口,如果没有实现接口则可以使用CGlib实现。

上一篇:HTML5工具初识之网页编辑器

下一篇:常用的Linux命令

QQ技术交流群

千锋Java开发官方①群
811099962

加入群聊