动态代理(Spring框架)

什么是动态代理?

举个例子,生活中一般在打官司的时候都会请代理律师,为什么要请律师呢?是因为开庭的时候大部人对于打官司没有经验,只会说出自己案件的陈述,并不会根据法律等争取自己权益的最大化,此时就可以请律师帮助自己不仅完成对案件的陈述,还能争取权益最大化。那么Java中也是一样,如果要对功能进行增强就可以使用动态代理

它通过java反射机制,获取某个被代理类的所有接口,并创建代理类 

为什么要用动态代理? 

动态代理使我们免于去重写接口中的方法,而着重于去扩展相应的功能或是方法的增强,与静态代理相比简单了不少,减少了项目中的业务量

Java的JDK中Proxy类可以实现基于接口的动态代理,实现步骤示例如下:

1.核心类的接口

package com.wang.service;

public interface Actor {
    void sring();

    void dance();

    void rap();
}

2. 实现核心接口中的抽象方法

package com.wang.service.impl;

import com.wang.service.Actor;

public class CXK implements Actor {
    @Override
    public void sring() {
        System.out.println("顶你太美");
    }

    @Override
    public void dance() {
        System.out.println("丁丁舞");
    }

    @Override
    public void rap() {
        System.out.println("练习时长两年半");
    }
}

3. 实现增强类

package com.wang.advice;

import com.wang.service.Actor;
import com.wang.service.impl.CXK;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JJGS {
    public static void main(String[] args) {
        //1.创建被代理类的对象----具体的人物cxk
        Actor cxk = new CXK();
        //2.创建代理的对象----具体某个人为上面cxk服务
        /**
         * Object proxy:被代理对象的引用,系统会自动创建被代理对象的一个映射
         * Method method:被代理对象的方法
         *  Object[] args:被代理对象方法的参数
         *  返回值是  被代理对象执行后的返回值
         */
        Actor jjr = (Actor) Proxy.newProxyInstance(CXK.class.getClassLoader(), CXK.class.getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                System.out.println("演出前的增强: 联系业务");
                System.out.println("演出前的增强:互联网造势");
                System.out.println("演出前的增强:演出前的宣传");

                //被代理对象方法的执行,并获得返回值
                Object result=null;
                result=method.invoke(cxk,args);

                System.out.println("演出后的增强: 结算费用并纳税");

                return result;
            }
        });
        //3.有代理对象执行方法的时候不再是被代理对象执行方法,而是由我们的代理类对象执行方法
        jjr.rap();
    }
}

基于子类的CGLib动态代理,可以使用Enhancer类完成直接对某个类进行动态代理。具体操作步骤如下:

导入lib中的jar包

 

1.核心类的接口

package com.wang.service;

public interface BookService {
    //添加
    int save(int n);

    //删除
    int del();

    //修改
    int update();

    //查询
    void find();
}

2.实现核心类的抽象方法

package com.wang.service.impl;

import com.wang.service.BookService;

public class BookServiceImpl implements BookService {
    @Override
    public int save(int n) {
        System.out.println("添加");
        return 1;
    }

    @Override
    public int del() {
        System.out.println("删除");
        return 1;
    }

    @Override
    public int update() {
        System.out.println("修改");
        return 1;
    }

    @Override
    public void find() {
        System.out.println("查询");
    }
}

3.编写代理类

package com.wang.advice;

public class Loger {
    public void before(){
        System.out.println("前置通知: 执行日志的打印");
    }
    public void after(){
        System.out.println("后置通知:执行日志的打印");
    }

    public void afterThrowingPrintLog(){
        System.out.println("异常通知");
    }

    public void afterPrintLog(){
        System.out.println("最终通知:作资源的释放");
    }
}

4编写动态代理的xml文件

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!-- 1.把所有类的对象交给IOC容器进行管理 -->
    <bean id="loger" class="com.wang.advice.Loger"/>
    <bean id="bookService" class="com.wang.service.impl.BookServiceImpl"/>


    <!-- 2.AOP的配置:让增强类 的 哪个方法  动态进行何种增强   核心类 的 哪个方法 -->
    <aop:config>
        <aop:aspect id="log" ref="loger">
            <aop:before method="before" pointcut="execution(* *..BookServiceImpl.*(..))"/>
            <aop:after-returning method="afterPrintLog" pointcut="execution(* *..BookServiceImpl.*(..))"/>
            <aop:after-throwing method="afterThrowingPrintLog" pointcut="execution(* *..BookServiceImpl.*(..))"/>
            <aop:after method="after" pointcut="execution(* *..BookServiceImpl.*(..))"/>
        </aop:aspect>
    </aop:config>
</beans>

5.测试类(执行核心文件中的添加方法,完成增强功能)

package com.wang.servlet;

import com.wang.service.BookService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test01 {

    @Test
    public void test01(){
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bookService = context.getBean(BookService.class);

        bookService.save(1);
    }
}

结果为:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值