动态代理原理介绍:

浅析Spring中AOP的实现原理——动态代理

 

SpringBoot使用AOP(动态代理)

  • cgllib 需要添加依赖
<!--cglib动态代理-->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.12</version>
</dependency>
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-aop</artifactId>
      <version>2.1.7.RELEASE</version>
  </dependency>

 

 

  1. 目标target(需要被增强的接口)
//目标target
public interface UserService {
    void login(String username, String password);
    void regist();
    void search();
    void update();
}

 

 

 

  1. 接口实现
/**
 * @Description
 * @Author zhoumm
 * @Version V1.0.0
 * @Since 1.0
 * @Date 2019-08-24
 */
@Service
public class UserServiceImpl implements UserService{
    @Override
    public void login(String username, String password) {
        System.out.println ("登录");
    }

    @Override
    public void regist() {
        System.out.println ("注册");
    }

    @Override
    public void search() {
        System.out.println ("userService search...");
    }

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

 

  1. 代理增强类
/**
 * @Description  代理增强类
 * @Author 
 * @Version V1.0.0
 * @Since 1.0
 * @Date 2019-08-25
 */
@Component
@Aspect  //标识为一个切面供容器读取
public class UserServiceHelper {
    @Before("execution(* com.mmz.tkp.controller.aoptest.UserService.s*(..))")
    public void before(){
        System.out.println ("前置通知。。。");
    }

    @AfterReturning(value="execution(* com.mmz.tkp.controller.aoptest.UserService.s*(..))")
    public void afterReturning(){
        System.out.println ("后置通知。。。");
    }

    @Around("execution(* com.mmz.tkp.controller.aoptest.UserService.s*(..))")
    public void around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println ("环绕前。。。");
        Object value = pjp.proceed();
        System.out.println (value);
        System.out.println ("环绕后。。。");
    }

    @After("execution(* com.mmz.tkp.controller.aoptest.UserService.s*(..))")
    public void after(){
        System.out.println ("最终通知。。。");
    }

    @AfterThrowing(value="execution(* *.s*(..))",throwing="ex")
    public void afterThrowing(JoinPoint jp,Throwable ex){
        System.out.println ("异常抛出通知" + ex);
    }

    @Pointcut("execution(* com.mmz.tkp.controller.aoptest.UserService.search(..))")
    public void mypointcut(){}

    @Pointcut("execution(* com.mmz.tkp.controller.aoptest.UserService.update(..))")
    public void mypointcut1(){}

    //使用@Pointcut来声明切点,避免在每个通知中定义切点
    @Before("mypointcut()||mypointcut1()")
    public void before1(){
        System.out.println ("前置通知。。。。");
    }
}

 

 

  1. JDK动态代理工厂类
/**
 * @Description JDK动态代理工厂类
 * 在运行期 ,在JVM内部动态生成class字节码对象(Class对象)
 * Jdk动态代理只针对于接口操作
 * @Author 
 * @Version V1.0.0
 * @Since 1.0
 * @Date 2019-08-24
 */
public class JDKProxyFactory implements InvocationHandler {
    //目标对象
    private Object target;

    public JDKProxyFactory(Object target) {
        this.target = target;
    }

    //使用Proxy创建代理对象
    public Object createProxy(){
        //目标类的类加载器对象
        ClassLoader classLoader = target.getClass().getClassLoader();
        //目标类的实现接口的Class[]
        Class<?>[] interfaces = target.getClass().getInterfaces();
        //当前对象需实现InvocationHandler接口
        return Proxy.newProxyInstance(classLoader,interfaces,this);
    }

    /**
     *
     * @param proxy  代理对象,一般不用
     * @param method 方法对象
     * @param args  方法参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //在调用目标对象方法前,统一做一些其他操作,即功能增强
        System.out.println ("例如:日志操作......");
        return method.invoke(target,args);
    }
}

 

  1. CGLIB动态代理
/**
 * @Description  CGLIB动态代理
 * CGLIB(Code Generation Library)是一个开源项目
 * 是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。
 * CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类
 *
 * 可以为没有实现接口的类去做代理,也可以为实现接口的类去做代理。
 *
 * spring采用的是哪一种动态机制:
 *     如果目标对象,有接口,优先使用jdk动态代理
 *     如果目标对象,无接口,使用cglib动态代理。
 * @Author zhoumm
 * @Version V1.0.0
 * @Since 1.0
 * @Date 2019-08-24
 */
public class CglibProxyFactory implements MethodInterceptor {
    //目标对象
    private Object target;

    public CglibProxyFactory(Object target) {
        this.target = target;
    }

    //创建代理对象
    public Object createProxy(){
        //1.创建Enhancer
        Enhancer enhancer = new Enhancer();
        //2.传递目标对象Class
        enhancer.setSuperclass(target.getClass());
        //3.设置回调操作(相当于InvocationHandler)
        enhancer.setCallback(this);

        return enhancer.create();
    }


    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        //在调用目标对象方法前,统一做一些其他操作,即功能增强
        System.out.println ("例如:日志操作......");
        return method.invoke(target,args);
    }
}

 

  1. controller 代理测试
@Api(value = "aop", description = "面向切面编程")
@RestController
@RequestMapping("/kpt/aop")
@Slf4j
@Validated
public class AopBackGroundController {

    @Autowired
    private UserService userService;

    @ApiOperation(value = "JDK动态代理测试", httpMethod = "GET")
    @RequestMapping(value = "/jdkproxy", method = RequestMethod.GET)
    public void testJDKProxy(){
        //JDK动态代理
        userService.login("zz","123456");
        System.out.println ("--------------JDK动态代理------------");
        JDKProxyFactory jdkProxyFactory = new JDKProxyFactory(userService);
        UserService userServiceProxy = (UserService)jdkProxyFactory.createProxy();
        userServiceProxy.login("zz","123456");
    }

    @ApiOperation(value = "CGLIB动态代理测试", httpMethod = "GET")
    @RequestMapping(value = "/cglibproxy", method = RequestMethod.GET)
    public void testCGLIBProxy(){
        //CGLIB动态代理
        userService.regist();
        System.out.println ("--------------CGLIB动态代理------------");
        CglibProxyFactory cglibProxyFactory = new CglibProxyFactory(userService);
        UserService userServiceProxy = (UserService)cglibProxyFactory.createProxy();
        userServiceProxy.regist();
    }

    @ApiOperation(value = "AspectJ代理测试", httpMethod = "GET")
    @RequestMapping(value = "/aspectJproxy", method = RequestMethod.GET)
    public void testAspectJ(){
        //com.mmz.tkp.controller.aoptest.UserServiceHelper
        userService.search();
    }

    @ApiOperation(value = "切点通知测试", httpMethod = "GET")
    @RequestMapping(value = "/aspectJproxy", method = RequestMethod.GET)
    public void testPointcutAdvice(){
        //com.mmz.tkp.controller.aoptest.UserServiceHelper
        userService.search();
    }
}

 

posted on 2020-08-06 22:04  yuluoxingkong  阅读(1593)  评论(0编辑  收藏  举报