IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Day381.AOP编程 -Spring5 -> 正文阅读

[Java知识库]Day381.AOP编程 -Spring5

AOP编程

?、静态代理设计模式

1. 为什么需要代理设计模式

1.1 问题

  • 在JavaEE分层开发开发中,那个层次对于我们来讲最重要

    • DAO —> Service --> Controller
    • JavaEE分层开发中,最为重要的是Service层
  • Service层中包含了哪些代码?

    • Service层中 = 核?功能(??? 上百代码) + 额外功能(附加功能)

      1. 核?功能

        业务运算
        DAO调?

      2. 额外功能

        不属于业务

        可有可?

        代码量很?

      事务、?志、性能…

  • 额外功能书写在Service层中好不好?

    Service层的调?者的?度(Controller):需要在Service层书写额外功能。

    软件设计者:Service层不需要额外功能

  • 现实?活中的解决?式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7dnhF7WV-1630847995054)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210904163337986.png)]


2. 代理设计模式

1.1 概念

通过代理类,为原始类(?标)增加额外的功能

好处:利于原始类(?标)的维护


1.2名词解释

  1. ?标类 原始类被代理类
    指的是 业务类 (核?功能 --> 业务运算 DAO调?)
  2. ?标?法,原始?法
    ?标类(原始类)中的?法 就是?标?法(原始?法)
  3. 额外功能 (附加功能)
    ?志,事务,性能

1.3 代理开发的核?要素

代理类 = ?标类(原始类) + 额外功能 + 原始类(?标类)实现相同的接?

房东 ---> public interface UserService{
            m1
            m2
}

UserServiceImpl implements UserService{
            m1 ---> 业务运算 DAO调?
            m2
}

UserServiceProxy implements UserService{
            m1
            m2
}

1.4 编码

静态代理为每?个原始类,??编写?个代理类 (.java .class)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nVQlmWom-1630847995058)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210904163518218.png)]


1.5 静态代理存在的问题

  1. 静态类?件数量过多,不利于项?管理
    UserServiceImpl —> UserServiceProxy
    OrderServiceImpl —> OrderServiceProxy
  2. 额外功能维护性差
    代理类中 额外功能 修改复杂(麻烦)

?、Spring的动态代理开发

1. Spring动态代理的概念

概念:通过代理类为原始类(?标类)增加额外功能
好处:利于原始类(?标类)的维护


2. 搭建开发环境

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>5.1.14.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.8.8</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.3</version>
</dependency>

3. Spring动态代理的开发步骤

  1. 创建原始对象(?标对象)

    public class UserServiceImpl implements UserService {
        @Override
        public void register(User user) {
            System.out.println("UserServiceImpl.register 业务运算 + DAO ");
        }
        @Override
        public boolean login(String name, String password) {
            System.out.println("UserServiceImpl.login");
            return true;
        }
    }
    
    <bean id="userService" class="com.baizhiedu.proxy.UserServiceImpl"/>
    
  2. 额外功能 MethodBeforeAdvice接?

    额外的功能书写在接?的实现中,运?在原始?法执?之前运?额外功能。

    public class Before implements MethodBeforeAdvice {
        /*
    作?:需要把运?在原始?法执?之前运?的额外功能,书写在before?法中
    */
        @Override
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println("-----method before advice log------");
        }
    }
    
    <bean id="before" class="com.baizhiedu.dynamic.Before"/> 
    
  3. 定义切?点

    切?点额外功能加?的位置
    ?的:由程序员根据??的需要,决定额外功能加?给那个原始?法
    register
    login
    简单的测试所有?法都做为切?点,都加?额外的功能。

    <aop:config>
        <aop:pointcut id="pc" expression="execution(* *(..))"/>
    </aop:config>
    
  4. 组装 (2/3步整合)

    表达的含义:所有的?法 都加? before的额外功能

    <aop:advisor advice-ref="before" pointcut-ref="pc"/>
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qjyTVgOm-1630847995066)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210904175847597.png)]

  5. 调?

    ?的:获得Spring??创建的动态代理对象,并进?调?

    ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
    

    注意:

    1. Spring的??通过原始对象的id值获得的是代理对象
    2. 获得代理对象后,可以通过声明接?类型,进?对象的存储
    UserService userService=(UserService)ctx.getBean("userService");
    userService.login("");
    userService.register();
    

在这里插入图片描述


4.动态代理细节分析

  1. Spring创建的动态代理类在哪??

    Spring框架在运?时,通过动态字节码技术,在JVM创建的,运?在JVM内部,等程序结束后,会和JVM?起消失
    什么叫动态字节码技术:通过第三个动态字节码框架,在JVM中创建对应类的字节码,进?创建对象,当虚拟机结束,动态字节码跟着消失。
    结论:动态代理不需要定义类?件,都是JVM运?过程中动态创建的,所以不会造成静态代理,类?件数量过多,影响项?管理的问题。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5gjAO6tD-1630847995076)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210904164015339.png)]

  1. 动态代理编程简化代理的开发

    在额外功能不改变的前提下,创建其他?标类(原始类)的代理对象时,只需要指定原始(?标)对象即可

  2. 动态代理额外功能的维护性??增强


三、Spring动态代理详解

1. 额外功能的详解

  • MethodBeforeAdvice分析

    1. MethodBeforeAdvice接?作?:额外功能运?在原始?法执?之前,进?额外功能操作。

      public class Before1 implements MethodBeforeAdvice {
          /*
      作?:需要把运?在原始?法执?之前运?的额外功能,书写在before?法中
      
      方法参数如下:↓↓↓↓↓↓↓
      Method: 额外功能所增加给的那个原始?法
              login?法
              register?法
              showOrder?法
      Object[]: 额外功能所增加给的那个原始?法的参数。
      		String name,String password
      		User user
      
      Object: 额外功能所增加给的那个原始对象 UserServiceImpl OrderServiceImpl
      */
          @Override
          public void before(Method method, Object[] args, Object target) throws Throwable {
              System.out.println("-----new method before advice log------");
          }
      
      }
      

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0xsaqF0q-1630847995078)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210904183821169.png)]

    2. before?法的3个参数在实战中,该如何使?。
      before?法的参数,在实战中,会根据需要进?使?,不?定都会?到,也有可能都不?

      Servlet{
          service(HttpRequest request,HttpResponse response){
              request.getParameter("name") -->
              response.getWriter() --->
          }
      }
      
  • MethodInterceptor(?法拦截器)推荐

    methodinterceptor接?:额外功能可以根据需要运?在原始?法执? 前、后、前后

    public class Arround implements MethodInterceptor {
        /*
    invoke?法的作?:额外功能书写在invoke
        额外功能 
        原始?法之前
        原始?法之后
        原始?法执?之前 之后
        确定:原始?法怎么运?
    参数:MethodInvocation (Method):额外功能所增加给的那个原始?法
        login
        register
        invocation.proceed() ---> login运?
        register运?
        
    返回值:Object: 原始?法的返回值
    Date convert(String name)
    */
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("-----额外功能 log----");
            Object ret = invocation.proceed();
            return ret;
        }
    }
    

    额外功能运?在原始?法执?之后

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable{
        Object ret = invocation.proceed();
        System.out.println("-----额外功能运?在原始?法执?之后----");
        return ret;
    }
    

    额外功能运?在原始?法执?之前,之后

    什么样的额外功能 运?在原始?法执?之前,之后都要添加?事务

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable{
        System.out.println("-----额外功能运?在原始?法执?之前----");
        Object ret = invocation.proceed();
        System.out.println("-----额外功能运?在原始?法执?之后----");
        return ret;
    }
    

    额外功能运?在原始?法抛出异常的时候

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable{
        Object ret = null;
        try {
            ret = invocation.proceed();
        } catch (Throwable throwable) {
            System.out.println("-----原始?法抛出异常 执?的额外功能 ---- ");
            throwable.printStackTrace();
        }
        return ret;
    }
    

    MethodInterceptor影响原始?法的返回值

    原始?法的返回值,直接作为invoke?法的返回值返回,MethodInterceptor不会影响原始?法的返回值
    MethodInterceptor影响原始?法的返回值
    Invoke?法的返回值,不要直接返回原始?法的运?结果即可

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable{
        System.out.println("------log-----");
        Object ret = invocation.proceed();
        return false;//不要直接返回原始?法的运?结果即可
    }
    

2. 切?点详解

切?点决定额外功能加?位置(?法)

<aop:pointcut id="pc" expression="execution(* *(..))"/>

exection( (…)) —> 匹配了所有?法 a b c

  1. execution() 切?点函数
  2. * *(…) 切?点表达式

2.1 切?点表达式

  1. ?法切?点表达式

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HKl7q8D5-1630847995079)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210905162319917.png)]

    * *(..) --> 所有?法
    
    * ---> 修饰符 返回值
    * ---> ?法名
    ()---> 参数表
    ..---> 对于参数没有要求 (参数有没有,参数有?个都?,参数是什么类型的都?)
    
    • 定义login?法作为切?点

      * login(..)
      
      # 定义 register 作为切?点
      * register(..)
      
    • 定义login?法且login?法有两个字符串类型的参数 作为切?点

      * login(String,String)
      
      # # 注意:? java.lang 包中的类型,必须要写 全限定名
      * register(com.achang.proxy.User)
      
      # .. 可以和具体的参数类型连?
      * login(String,..) -->
      login(String),login(String,String),login(String,com.baizhiedu.proxy.User)
      
    • 精准?法切?点限定

      修饰符 返回值 包.类.?法(参数)
      
      * com.achang.proxy.UserServiceImpl.login(..)
      
      * com.achang.proxy.UserServiceImpl.login(String,String)
      
  2. 切?点·

    指定特定类作为切?点(额外功能加?的位置),?然这个类中的所有?法,都会加上对应的额外功能

    • 语法1

       # 类中的所有?法加?了额外功能
      * com.achang.proxy.UserServiceImpl.*(..)
      
    • 语法2

       # 忽略包
      1. 类只存在 ?级 包 com.UserServiceImpl
      * *.UserServiceImpl.*(..)
      2. 类存在 多级 包 com.achang.proxy.UserServiceImpl
      * *..UserServiceImpl.*(..)
      

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-joOakPg2-1630847995081)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210905170839338.png)]

  3. 切?点表达式 实战

    指定包作为额外功能加?的位置,?然包中的所有类及其?法都会加?额外的功能

    • 语法1

      # # 切?点包中的所有类,必须在 proxy 中,不能在 proxy 包的?包中
      * com.achang.proxy.*.* (..)
      
    • 语法2

       # 切?点当前包及其?包都?效
      * com.achang.proxy..*.* (..)
      

2.2 切?点函数

切?点函数?于执?切?点表达式

  1. execution

    最为重要的切?点函数,功能最全。

    • 执??法切?点表达式、类切?点表达式、包切?点表达式
    弊端:execution执?切?点表达式 ,书写麻烦
    execution(* com.baizhiedu.proxy..*.*(..))
    注意:其他的切?点函数 简化是execution书写复杂度,功能上完全?致
    
  2. args

    作?:主要?于函数(?法) 参数的匹配
    切?点:?法参数必须得是2个字符串类型的参数
    execution( * * (String,String))
    args(String,String)
    
  3. within

    作?:主要?于进?类、包切?点表达式的匹配
    切?点:UserServiceImpl这个类
    
    execution( * * ..UserServiceImpl. *(..))
    within( *..UserServiceImpl)
    
    execution( * com.achang.proxy..* . *(..))
    within(com.achang.proxy..*)
    
  4. @annotation

    作?:为具有特殊注解的?法加?额外功能

    <aop:pointcut id="pc" expression="@annotation(com.baizhiedu.Log)"/>
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GO8MMWFs-1630847995083)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210905184013200.png)]

    组装中的arround,自定义注解的实现,通过实现MethodInterceptor;pc是自定义注解

  5. 切?点函数的逻辑运算

    指的是 整合多个切?点函数?起配合?作,进?完成更为复杂的需求

    • and与操作

      案例:login 同时 参数 2个字符串
      1. execution( * login(String,String))
      2. execution( * login(..)) and args(String,String)
      
      注意:与操作不同?于同种类型的切?点函数
      
      案例:register?法 和 login?法作为切?点 xxxxxxxxxxxxxxxxxxxx
      execution( * login(..)) or execution(* register(..))
      
    • or或操作

      案例:register?法 和 login?法作为切?点
      execution( * login(..)) or execution(* register(..))
      

四、AOP编程

1. AOP概念

本质就是Sprind的动态代理开发,通过代理类为原始类增加额外功能
好处:利于原始类的维护
注意AOP编程不可能取代OOP,OOP编程有意补充

  • AOP (Aspect Oriented Programing)

    ?向切?编程 = Spring动态代理开发
    以切?为基本单位的程序开发,通过切?间的彼此协同,相互调?,完成程序的构建
    切? = 切?点 + 额外功能

  • OOP (Object Oriented Programing) ?向对象编程 Java
    以对象为基本单位的程序开发,通过对象间的彼此协同,相互调?,完成程序的构建

  • POP (Producer Oriented Programing) ?向过程(?法、函数)编程 C
    以过程为基本单位的程序开发,通过过程间的彼此协同,相互调?,完成程序的构建


2. AOP编程的开发步骤

  1. 原始对象
  2. 额外功能 (MethodInterceptor)
  3. 切?点
  4. 组装切? (额外功能+切?点)

3. 切?的名词解释

  • 切? = 切?点 + 额外功能
    ?何学
  • ? = 点 + 相同的性质

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MZCm3PlM-1630847995085)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210905193922290.png)]


五、AOP的底层实现原理

1. 核?问题

  1. AOP如何创建动态代理类(动态字节码技术)
  2. Spring??如何加?创建代理对象
    通过原始对象的id值,获得的是代理对象

2. 动态代理类的创建

2.1 JDK的动态代理

  • Proxy.newProxyInstance?法参数详解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QpTGpFqu-1630847995088)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210905195444405.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PxTlladh-1630847995090)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210905193526461.png)]

  • 编码
public class TestJDKProxy {
    /*
        1. 借?类加载器 TestJDKProxy、UserServiceImpl
        2. JDK8.x前
        final UserService userService = new UserServiceImpl();
        */
    public static void main(String[] args) {
        //1 创建原始对象
        UserService userService = new UserServiceImpl();
        //2 JDK创建动态代理
        /**/
        //额外功能,通过内部类的形式创建
        InvocationHandler handler = new InvocationHandler(){
            @Override
            public Object invoke(Object proxy, Method method,Object[] args) throws Throwable {
                System.out.println("------proxy log --------");
                //原始?法运?
                Object ret = method.invoke(userService, args);
                return ret;
            }
        };
        UserService userServiceProxy =(UserService)Proxy.newProxyInstance(UserServiceImpl.class.getClassLoader(),userService.getClass().getInterfaces(),handler);
        userServiceProxy.login("achang", "123456");
        userServiceProxy.register(new User());
    }
}

2.2 CGlib的动态代理

CGlib创建动态代理的原理:??继承关系创建代理对象,原始类作为?类,代理类作为?类,这样既可以保证2者?法?致,同时在代理类中提供新的实现(额外功能+原始?法)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LLLf7mqW-1630847995092)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210905201901572.png)]

  • CGlib编码
package com.achang.cglib;

import com.achang.proxy.User;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class TestCglib {
    public static void main(String[] args) {
        //1 创建原始对象
        UserService userService = new UserService();
        /*
    2 通过cglib?式创建动态代理对象
        Proxy.newProxyInstance(classloader,interface,invocationhandler)
        
        Enhancer.setClassLoader()
        Enhancer.setSuperClass()
        Enhancer.setCallback(); ---> MethodInterceptor(cglib)
        Enhancer.create() ---> 代理
    */
        Enhancer enhancer = new Enhancer();
        enhancer.setClassLoader(TestCglib.class.getClassLoader());
        enhancer.setSuperclass(userService.getClass());
        MethodInterceptor interceptor = new MethodInterceptor() {
            //等同于 InvocationHandler --- invoke
            @Override
            public Object intercept(Object o, Method method,Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("---cglib log----");
                Object ret = method.invoke(userService, args);
                return ret;
            }
        };
        enhancer.setCallback(interceptor);
        UserService userServiceProxy = (UserService)enhancer.create();
        
        userServiceProxy.login("achang", "1233456");
        userServiceProxy.register(new User());
    }
}
  • 总结
  1. JDK动态代理 Proxy.newProxyInstance() 通过接?创建代理的实现类
  2. Cglib动态代理 Enhancer 通过继承?类创建的代理类

3. Spring??如何加?原始对象

  • 思路分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KZzfXW59-1630847995096)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210905203451758.png)]

  • 编码
public class ProxyBeanPostProcessor implements BeanPostProcessor {
    
    @Override
    public Object postProcessBeforeInitialization(Object bean,String beanName) throws BeansException {
        return bean;
    }
    
    @Override
    public Object postProcessAfterInitialization(Object bean,String beanName) throws BeansException {
        //额外内容,通过内部类的形式创建
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method,Object[] args) throws Throwable {
                System.out.println("----- new Log-----");
                Object ret = method.invoke(bean, args);
                return ret;
            }
        };

        //通过JDK的动态代理包的Proxy.newProxyInstance()生成代理对象并返回代理对象
        return Proxy.newProxyInstance(ProxyBeanPostProcessor.class.getClassLoader(),bean.getClass().getInterfaces(),handler);
    }
}
<!--原始对象,被代理对象-->
<bean id="userService" class="com.baizhiedu.factory.UserServiceImpl"/>

<!--
开发BeanPostProcessor流程:↓
1. 实现BeanPostProcessor 进?加?
2. 配置?件中对BeanPostProcessor进?配置
-->
<bean id="proxyBeanPostProcessor" class="com.achang.factory.ProxyBeanPostProcessor"/>

六、基于注解的AOP编程

1. 基于注解的AOP编程的开发步骤

  1. 原始对象
  2. 额外功能
  3. 切?点
  4. 组装切?
# 通过切?类 定义了 额外功能 @Around
定义了 切?点 @Around("execution(* login(..))")
@Aspect 切?类
package com.achang.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
/*
1. 额外功能【之前我们创建额外功能】
public class MyArround implements
MethodInterceptor{
    public Object invoke(MethodInvocation invocation){
    Object ret =
    invocation.proceed();
    return ret;
    }
}
2. 切?点【配置切入点】
<aop:config
<aop:pointcut id="" expression="execution(* login(..))"/>
*/

//切面类
@Aspect
public class MyAspect {
    
   	//切入点表达式,指定切入的方法
    @Around("execution(* login(..))")
    //额外功能
    public Object arround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("----aspect log ------");
        Object ret = joinPoint.proceed();
        return ret;
    }
}
<!--原始对象,被代理对象-->
<bean id="userService" class="com.achang.aspect.UserServiceImpl"/>

<!--
切?
    1. 额外功能
    2. 切?点
    3. 组装切?
-->
<bean id="arround" class="com.achang.aspect.MyAspect"/>

<!--告知Spring基于注解进?AOP编程-->
<aop:aspectj-autoproxy />

2. 细节

  1. 切?点复?

    在切?类中定义?个函数 上?@Pointcut注解 通过这种?式,定义切?点表达式,后续更加有利于切?点复?。

    @Aspect
    public class MyAspect {
        //提供切?点复?
        @Pointcut("execution(* login(..))")
        public void myPointcut(){}
        
    	//切?点复?
        @Around(value="myPointcut()")
        public Object arround(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("----aspect log ------");
            Object ret = joinPoint.proceed();
            return ret;
        }
    
        //切?点复?
        @Around(value="myPointcut()")
        public Object arround1(ProceedingJoinPoint joinPoint)
            throws Throwable {
            System.out.println("----aspect tx ------");
            Object ret = joinPoint.proceed();
            return ret;
        }
    
    }
    
  2. 动态代理的创建?式

    AOP底层实现 2种代理创建?式

    1. JDK 通过实现接? 做新的实现类?式 创建代理对象
    2. Cglib通过继承?类 做新的?类 创建代理对象

    默认情况 AOP编程 底层应?JDK动态代理创建?式

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E9Iq55ye-1630847995097)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210905205749663.png)]

    如何切换Cglib???

    proxy-target-class="true",即可切换为Cglib

    #1. 基于注解AOP开发
    <aop:aspectj-autoproxy proxy-target-class="true"/></aop>
    
    #2. 传统的AOP开发
    <aop:config proxy-target-class="true"></aop>
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-52JPaaXg-1630847995099)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210905205942272.png)]


七、AOP开发中的?个坑

  • 在同?个业务类中,进?业务?法间的相互调?,只有最外层的?法,才是加?了额外功能(内部的?法,通过普通的?式调?,都调?的是原始?法)。

    如果想让内层的?法也调?代理对象的?法,就要AppicationContextAware获得??,进?获得代理对象

public class UserServiceImpl implements UserService,ApplicationContextAware {
    private ApplicationContext ctx;
    
    //通过实现ApplicationContextAware,来获取工程对象,聚合赋值
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.ctx = applicationContext;
    }
    
    @Log
    @Override
    public void register(User user) {
        System.out.println("UserServiceImpl.register 业务运算 + DAO ");
        //throw new RuntimeException("测试异常");
        //调?的是原始对象的login?法 ---> 核?功能
        /*
        设计?的:代理对象的login?法 ---> 额外功能+核?功能
            ApplicationContext ctx = new
            ClassPathXmlApplicationContext("/applicationContext2.xml");
            UserService userService = (UserService)
            ctx.getBean("userService");
            userService.login();
        Spring??重量级资源 ?个应?中 应该只创建?个??
        */
        UserService userService = (UserService)ctx.getBean("userService");
        userService.login("suns", "123456");
    }![image-20210905211916373](C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210905211916373.png)
    @Override
    public boolean login(String name, String password) {
        System.out.println("UserServiceImpl.login");
        return true;
    }
}

?、AOP阶段知识总结

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DUhpXYO6-1630847995101)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210905211918740.png)]


  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-09-06 11:02:26  更:2021-09-06 11:03:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:06:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码