动态代理几种实现方式(JDK+AOP)

2023-05-16

文章目录

  • 第一种:JDK动态代理
  • 第二种:使用springAPI接口实现
  • 第三种:diy类实现
  • 第四种:使用注解

第一种:JDK动态代理

这里可以看我写的这两篇博客,我觉得已经很详细:
且来玩一玩动态代理(极深度版本)

第二种:使用springAPI接口实现

方式顺序:(纯属口述,可能会有些不符合规范)

  1. 定义接口
  2. 定义接口的实现类
  3. 定义好要插入的新内容的类
  4. applicationContext.xml配置好接口实现类以及“内容类”
  5. aop配置(配置要对哪个实现类的方法进行切入)
    如果是要在切入点之前执行,实现MethodBeforeAdvice 接口
    之后的话就实现AfterReturningAdvice接口
  6. 测试

pointcut+advisor配合

接口:
UserService.java

package com.xmonster.service;

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void select();

}

实现类(被代理对象)
UserServiceImpl.java

package com.xmonster.service;

public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加了一个用户");
    }

    @Override
    public void delete() {
        System.out.println("删除了一个用户");
    }

    @Override
    public void update() {
        System.out.println("修改了一个用户");
    }

    @Override
    public void select() {
        System.out.println("查询了一个用户");
    }
}

定义要插入的内容的类

package com.xmonster.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Log implements MethodBeforeAdvice {

//   Method:要执行的目标对象的方法
//    Object:参数
//    target:目标对象
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {

        System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
    }
}

package com.xmonster.log;

import org.springframework.aop.AfterAdvice;
import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class AfteLog implements AfterReturningAdvice {
//   returnValue: 返回值
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了"+method.getName()+"方法,返回结果为:"+returnValue);
    }
}

💘 applicationContext.xml配置

<?xml version="1.0" encoding="UTF8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd
">
<!--    注册bean-->
    <bean id="userService" class="com.xmonster.service.UserServiceImpl"/>
    <bean id="log" class="com.xmonster.log.Log"/>
    <bean id="afterlog" class="com.xmonster.log.AfteLog"/>

<!--    方式一:使用原生的api接口-->
<!--    配置AOP-->
    <aop:config>
<!--        切入点:就是找需要在哪里执行spring的方法-->
<!--        expression是一个表达式 execution要执行的位置! -->
        <aop:pointcut id="pointcut" expression="execution(* com.xmonster.service.UserServiceImpl.*(..) )"/>
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterlog" pointcut-ref="pointcut"/>
    </aop:config>
</beans>

测试

import com.xmonster.service.UserService;
import com.xmonster.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//       动态代理代理的是接口!!
        UserService userService = (UserService) context.getBean("userService");
        userService.add();

    }
}

在这里插入图片描述

第三种:diy类实现

可以理解成自定义了一个切面,用切面+切入点
aspect+pointcut+before.....配合
通过自定义的切面(类)来玩,这种方式比较容易一些,它把同类型的要通知或者要进行安全验证的类都写在各自的自定义的类中
UserService和UserServiceImpl和上面一样不变,测试类也不变
以下是
自定义的类:
diy.java

package com.xmonster.diy;

import org.aspectj.lang.annotation.After;

public class Diy {
    public void before(){
        System.out.println("=======方法执行前=======");
    }

    public void after(){
        System.out.println("=======方法执行后=======");
    }
}

配置

<?xml version="1.0" encoding="UTF8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd
">
<!--    方式二:自定义类-->
    <bean id="userService" class="com.xmonster.service.UserServiceImpl"/>
    <bean id="diy" class="com.xmonster.diy.Diy"/>
    
    <aop:config>
        <aop:aspect ref="diy">
            <aop:pointcut id="point" expression="execution(* com.xmonster.service.UserServiceImpl.*(..))"/>
            
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
            
        </aop:aspect>
    </aop:config>
   
</beans>

第四种:使用注解

这种方式是最容易的方式了,但是这里有一个不是很方便的就是要重写切入点这个操作,不是很方便,如果你要插入的是比较复杂的,方法有很多的,尽量还是写入配置文件中比较方便维护
DiyPointCut.java

package com.xmonster.diy;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class DiyPointCut {

    @Before("execution(* com.xmonster.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("=======方法执行前=======");
    }

    @After("execution(* com.xmonster.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("=======方法执行后=======");
    }

}

在配置文件中将切面类和被代理类注册好之后,别忘了加上:

<!--    第三种:使用注解来实现-->
    <aop:aspectj-autoproxy proxy-target-class="true"/>

开启注解

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

动态代理几种实现方式(JDK+AOP) 的相关文章

随机推荐