Spring静态代理与动态代理

什么是动态代理?

使用jdk的反射机制,创建对象的能力,创建的是代理类的对象。而不用你创建类文件。不用谢java文件。

​ 动态:在程序执行时,调用JDK提供的方法才能创建代理类的对象。

​jdk动态代理,必须有接口,目标类必须实现接口,没有接口时,需要使用cylib动态代理。

动态代理能做什么?

​ 可以在不改变原来目标方法功能的前提下,可以在代理中增强自己的功能代码。

​ 程序开发中的意思。

​ 比如:你所在的项目中,有一个功能是其他人(公司的其他部门,其他小组的人)写好的,你可以使用。

​ GoNong.class , GoNong gn = new GoNong(), gn,print();

​ 你发现这个功能,现在还缺点,不能完全满足我项目的需要,我需要在gn.print()执行后,需要自己在增强代码。

​ 用代理实现gn.print()调用时,增加自己代理,而不用去改变原来GoNang文件。

为什么要使用动态代理?

请看如下例子,一个演员的本质工作是做音乐表演、舞蹈表演、娱乐表演等,但是目前疫情管控,演出前不得不配合政府做好防疫管控。最基本的实现方法是直接对方法进行改造,添加对应的功能。

用代理模式的作用

​ 1.功能增强 :在你原有的功能上,增强了额外的功能。新增加的功能,叫做功能增强。

​ 2.控制访问: 代理类不让你访问目标,例如商家不让用户访问厂家。

实现代理的方式:

1.静态代理:
​ 1)代理类是自己手工实现的,自己创建一个java类,表示代理类。

​ 2)同时你所要代理的目标类是确定(固定)的。

特点:

  • 实现简单
  • 容易理解。

​ 缺点:当你的项目中,目标类和代理类很多时候,有以下的缺点:

  • ​ 当目标类增加了,代理类可能也需要成倍的增加。代理类数量过多。
  • 当你的接口中功能增加了,或者修改了,会影响众多的实现类,厂家类,代理都需要修改,影响比较大
/* 接口*/
public interface Actor {
    void  sing(int money);
    String dance();
    void rap();
}
/*实现类*/
public class Ck implements Actor {
    @Override
    public void sing(int money) {
        System.out.println("唱"+money);
    }

    @Override
    public String dance() {
        System.out.println("街舞");
        return  "nick";
    }

    @Override
    public void rap() {
        System.out.println("山河志");
    }
}

 测试类

public class gsgc {
    public static void main(String[] args) {
//        1.创建被代理类的对象
        Actor c=new Ck();

//        2.创建代理对象--具体到个人
        /**
         *
         * ClassLoader loader:类的加载器
         *Class<?>[] interfaces:类的接口类型
         * InvocationHandler h:处理器
         */
        Actor jjr= (Actor) Proxy.newProxyInstance(Ck.class.getClassLoader(), Ck.class.getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object result=null;
                result=method.invoke(Ck,args);
                return result;
            }
        });
        jjr.sing(550);
    }
}

2 .动态代理

在静态dialing中目标类很多时候,可以使用动态代理,避免静态代理的缺点。

动态代理中目标类即使很多,1>代理类数量可以很少 ,2>当你修改了接口中的方法时,不会影响代理类。

动态代理:在程序执行过程中,使用jdk的反射机制,创建代理类对象,并动态的指定要代理目标类。

换句话说,动态代理是一种创建java对象的能力,让你不用创建TaoBao类,就能创建代理类对象。

在java中,要想创建对象: 1)创建类文件,java文件编译为class 2)使用构造方法,创建类的对象

核心类

/*接口*/
public interface BookService {
    int save(int n);
    void del();
    void update();
    void find();
}
/*实现类内容*/
 @Override
    public int save(int n) {
        int a=5/0;
        return 1;
    }

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

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

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

增强类

public class Loger {
    public  void  check(){
        System.out.println("前置通知/增强:执行系统权限验证");
    }
    public  void  logPrint(){
        System.out.println("后置通知/增强:执行日志打印");
    }
    public  void  exception(){
        System.out.println("异常通知/增强:做出异常处理");
    }
    public  void  distory(){
        System.out.println("最终通知/增强:资源释放");
    }


}

测试类

public class Text {
    @Test
    public  void  text01(){
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bean = context.getBean(BookService.class);

        bean.save(1);
    }
}

spring核心配置文件

<?xml version="1.0" encoding="UTF-8"?>
<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.T.advice.Loger"/>
    <bean id="bookService" class="com.T.service.Impl.BookServiceImpl"/>
    <!--2.AOP的配置:让增强类 的 哪个方法  动态进行何种增强   核心类 的 哪个方法-->
    <aop:config>
        <aop:aspect id="log" ref="loger">
<!--            <aop:after method="check" pointcut="execution(void com.T.service.Impl.BookServiceImpl.save())"/>-->
            <!-- 前置通知/增强-->
            <aop:before method="check" pointcut="execution(* *..BookServiceImpl.*(..))"/>
            <!-- 后置通知/增强-->
            <aop:after-returning method="logPrint" pointcut="execution(* *..BookServiceImpl.*(..)))"/>
            <!-- 异常通知/增强-->
            <aop:after-throwing method="exception" pointcut="execution(* *..BookServiceImpl.*(..))"/>
            <!-- 最终通知/增强-->
            <aop:after method="distory" pointcut="execution(* *..BookServiceImpl.*(..))"/>
        </aop:aspect>
    </aop:config>

</beans>

Advice在Spring AOP中对应API

上面说到的Aspject中的注解,其中有五个是用来定义Advice的,表示代理逻辑,以及执行时机:

  • @Before
  • @AfterReturning
  • @AfterThrowing
  • @After
  • @Around

Spring自己也提供了类似的执行实际的实现类:

  • 接口MethodBeforeAdvice,继承了接口BeforeAdvice
  • 接口AfterReturningAdvice
  • 接口ThrowsAdvice
  • 接口AfterAdvice
  • 接口MethodInterceptor

Spring会把五个注解解析为对应的Advice类:

  • @Before:AspectJMethodBeforeAdvice,实际上就是一个MethodBeforeAdvice
  • @AfterReturning:AspectJAfterReturningAdvice,实际上就是一个AfterReturningAdvice
  • @AfterThrowing:AspectJAfterThrowingAdvice,实际上就是一个MethodInterceptor
  • @After:AspectJAfterAdvice,实际上就是一个MethodInterceptor
  • @Around:AspectJAroundAdvice,实际上就是一个MethodInterceptor
  • 接口AfterReturningAdvice
  • 接口ThrowsAdvice
  • 接口AfterAdvice
  • 接口MethodInterceptor
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值