cglib动态代理、jdk动态代理及spring动态代理使用

1.项目初始化

1.1 pom.xml

<dependencies>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-contextartifactId>
            <version>5.2.5.RELEASEversion>
        dependency>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-txartifactId>
            <version>5.2.5.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-jdbcartifactId>
            <version>5.2.5.RELEASEversion>
        dependency>
        
        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatisartifactId>
            <version>3.5.1version>
        dependency>
        
        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatis-springartifactId>
            <version>1.3.1version>
        dependency>
        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.9version>
        dependency>
        
        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>druidartifactId>
            <version>1.1.12version>
        dependency>
        
        <dependency>
            <groupId>org.aspectjgroupId>
            <artifactId>aspectjrtartifactId>
            <version>1.9.5version>
        dependency>
         <dependency>
            <groupId>org.apache.geronimo.bundlesgroupId>
            <artifactId>aspectjweaverartifactId>
            <version>1.6.8_2version>
        dependency>
    dependencies>

1.2UserService对象

package com.nq.service;

import org.springframework.stereotype.Component;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/29 23:04
 */
@Component
public class UserService {

    public void test(){
        System.out.println("test方法。");
    }

    public void a(){
        System.out.println("a方法。");
    }
}

cglib动态代理、jdk动态代理及spring动态代理使用_第1张图片

2.cjlib动态代理的使用

2.1所有的方法都是使用动态代理

package com.nq.service;

import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/29 23:29
 */
public class CglibTest {
    public static void main(String[] args) {
        UserService target =new UserService();

        Enhancer enhancer=new Enhancer();
        enhancer.setSuperclass(UserService.class);

        enhancer.setCallbacks(new Callback[]{new MethodInterceptor() {
                    @Override
                    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                        System.out.println("before...");

                        //被代理的对象,目标方法
                        //Object result=methodProxy.invoke(target,objects);
                        //Object result=method.invoke(target,objects);
                        Object result=methodProxy.invokeSuper(o,objects);


                        System.out.println("After...");
                        return  result;
                    }
                }
        });

        UserService userService = (UserService) enhancer.create();
        userService.test();
    }
}

2.2不同的方法使用不同的代理

package com.nq.service;

import org.springframework.cglib.proxy.*;

import java.lang.reflect.Method;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/29 23:29
 */
public class CglibTest {
    public static void main(String[] args) {
        UserService target =new UserService();

        Enhancer enhancer=new Enhancer();
        enhancer.setSuperclass(UserService.class);

        enhancer.setCallbacks(new Callback[]{new MethodInterceptor() {
                    @Override
                    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                        System.out.println("before...");

                        //被代理的对象,目标方法
                        //Object result=methodProxy.invoke(target,objects);
                        //Object result=method.invoke(target,objects);
                        Object result=methodProxy.invokeSuper(o,objects);


                        System.out.println("After...");
                        return  result;
                    }
                }
                , NoOp.INSTANCE});

        enhancer.setCallbackFilter(new CallbackFilter() {
            @Override
            public int accept(Method method) {
                if("test".equals(method.getName())){//表示test方法执行第一个代理方法,其他方法执行第二个方法
                    return 0;
                }else{
                    return 1;
                }
            }
        });
        UserService userService = (UserService) enhancer.create();
        userService.a();
    }
}

3.jdk动态代理的使用

3.1UserInterface创建接口

package com.nq.service;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/29 23:58
 */
public interface UserInterface {

    void test();

    void a();
}

3.2UserService实现接口

package com.nq.service;

import org.springframework.stereotype.Component;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/29 23:04
 */
@Component
public class UserService implements UserInterface{

    public void test(){
        System.out.println("test方法。");
    }

    public void a(){
        System.out.println("a方法。");
    }
}

3.3JdkTest代理的main方法

package com.nq.service;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/29 23:56
 */
public class JdkTest {
    public static void main(String[] args) {
        UserInterface target=new UserService();
        UserInterface userInterface =(UserInterface) Proxy.newProxyInstance(JdkTest.class.getClassLoader(), new Class[]{UserInterface.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("Jdk动态代理被执行了,方法之前");
                method.invoke(target,args);
                System.out.println("Jdk动态代理被执行了,方法之后");
                return null;
            }
        });
        userInterface.test();
    }
}

cglib动态代理、jdk动态代理及spring动态代理使用_第2张图片

4.spring中动态代理的使用

4.1proxyFactory 动态代理的使用方法

NickelBeforeAdvice.java方法执行之前

package com.nq.advice;

import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/30 0:59
 */
public class NickelBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("方法执行前被执行了");
    }
}

NickelAfterReturningAdvice.java方法执行之后

package com.nq.advice;

import org.aspectj.lang.annotation.AfterReturning;
import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/30 0:59
 */
public class NickelAfterReturningAdvice implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("方法returning被执行了");
    }
}

NickelAroundadvice.java环绕方法

package com.nq.advice;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/30 0:59
 */
public class NickelAroundadvice implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("方法执行round之前");
        Object proceed = invocation.proceed();
        System.out.println("方法执行round之后");
        return proceed;
    }
}

NickelThrowAdvice.java抛异常方法

package com.nq.advice;

import org.springframework.aop.ThrowsAdvice;

import java.lang.reflect.Method;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/30 1:00
 */
public class NickelThrowAdvice implements ThrowsAdvice {

    public void afterThrowing(Method method, Object[] args, Object target, NullPointerException ex) {
        System.out.println("方法抛异常执行了");
    }
}

UserService.java抛异常方法

package com.nq.service;

import org.springframework.stereotype.Component;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/29 23:04
 */
@Component
public class UserService implements UserInterface{

    public void test(){
        System.out.println("test方法。");
    }

    public void a(){
        System.out.println("a方法。");
        throw  new NullPointerException();
    }
}

SpringProxtFactoryTest.java测试方法

package com.nq.service;

import com.nq.advice.NickelAfterReturningAdvice;
import com.nq.advice.NickelAroundadvice;
import com.nq.advice.NickelBeforeAdvice;
import com.nq.advice.NickelThrowAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;

import java.lang.reflect.Method;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/30 0:49
 */
public class SpringProxtFactoryTest {
    public static void main(String[] args) {
        UserService target=new UserService();

        ProxyFactory proxyFactory=new ProxyFactory();
        proxyFactory.setTarget(target);
        //proxyFactory.setInterfaces(UserInterface.class);这里可以指定为接口类型
        proxyFactory.addAdvice(new NickelAroundadvice());
        proxyFactory.addAdvice(new NickelBeforeAdvice());
        UserService userService = (UserService) proxyFactory.getProxy();
        userService.test();

    }
}

cglib动态代理、jdk动态代理及spring动态代理使用_第3张图片

4.2proxyFactory 对方法名字进行限制

NickelStaticMethodMatherPointcut.java方法匹配的方法

package com.nq.advice;

import org.springframework.aop.support.StaticMethodMatcherPointcut;

import java.lang.reflect.Method;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/30 1:39
 */
public class NickelStaticMethodMatherPointcut extends StaticMethodMatcherPointcut {
    @Override
    public boolean matches(Method method, Class<?> aClass) {
        return method.getName().equals("test");
    }
}

NickelPointcutAdvisor.java切面方法

package com.nq.advice;

import org.aopalliance.aop.Advice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.aop.support.StaticMethodMatcherPointcut;

import java.lang.reflect.Method;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/30 1:34
 */
public class NickelPointcutAdvisor implements PointcutAdvisor {
    @Override
    public Pointcut getPointcut() {
        return new NickelStaticMethodMatherPointcut();
    }

    @Override
    public Advice getAdvice() {
        return new NickelBeforeAdvice();
    }

    @Override
    public boolean isPerInstance() {
        return false;
    }
}

SpringProxtFactoryTest.java测试的方法

package com.nq.service;

import com.nq.advice.*;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;

import java.lang.reflect.Method;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/30 0:49
 */
public class SpringProxtFactoryTest {
    public static void main(String[] args) {
        UserService target=new UserService();

        ProxyFactory proxyFactory=new ProxyFactory();
        proxyFactory.setTarget(target);
        //proxyFactory.setInterfaces(UserInterface.class);这里可以指定为接口类型
        //proxyFactory.addAdvice(new NickelAroundadvice());
        //proxyFactory.addAdvice(new NickelBeforeAdvice());
        proxyFactory.addAdvisor(new NickelPointcutAdvisor());
        UserService userService = (UserService) proxyFactory.getProxy();
        userService.test();

    }
}

cglib动态代理、jdk动态代理及spring动态代理使用_第4张图片
cglib动态代理、jdk动态代理及spring动态代理使用_第5张图片

4.3spring中的动态代理方式

4.3.1spring执行方法时候启动逻辑

UserService.java修改

package com.nq.service;

import org.springframework.stereotype.Component;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/29 23:04
 */
public class UserService{

    public void test(){
        System.out.println("test方法。");
    }

    public void a(){
        System.out.println("a方法。");
        //throw  new NullPointerException();
    }
}

说明:这里需要去掉Component注解


AppConfig.java配置

package com.nq.service;


import com.nq.advice.NickelAfterReturningAdvice;
import com.nq.advice.NickelBeforeAdvice;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/28 14:59
 */
@ComponentScan("com.nq")
public class AppConfig {

    @Bean
    public ProxyFactoryBean userService(){
        UserService userService=new UserService();
        ProxyFactoryBean proxyFactoryBean=new ProxyFactoryBean();
        proxyFactoryBean.addAdvice(new NickelAfterReturningAdvice());
        proxyFactoryBean.setTarget(userService);
        return proxyFactoryBean;
    }

}

Test.java配置

package com.nq.service;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/29 23:00
 */

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext();
        context.register(AppConfig.class);
        context.refresh();

        UserService userService = (UserService) context.getBean("userService");
        userService.test();
    }
}

启动Test.java显示结果
cglib动态代理、jdk动态代理及spring动态代理使用_第6张图片

4.3.2不去掉注解,spring执行方法的时候执行对应的逻辑

修改NickelAfterReturningAdvice.Java,增加注解

package com.nq.advice;

import org.aspectj.lang.annotation.AfterReturning;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/30 0:59
 */
@Component
public class NickelAfterReturningAdvice implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("方法returning被执行了");
    }
}

修改UserService.Java,增加注解

package com.nq.service;

import org.springframework.stereotype.Component;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/29 23:04
 */
@Component
public class UserService{

    public void test(){
        System.out.println("test方法。");
    }

    public void a(){
        System.out.println("a方法。");
        //throw  new NullPointerException();
    }
}

修改AppConfig.Java配置文件

package com.nq.service;


import com.nq.advice.NickelAfterReturningAdvice;
import com.nq.advice.NickelBeforeAdvice;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/28 14:59
 */
@ComponentScan("com.nq")
public class AppConfig {

    @Bean
    public BeanNameAutoProxyCreator beanNameAutoProxyCreator(){
        BeanNameAutoProxyCreator beanNameAutoProxyCreator=new BeanNameAutoProxyCreator();
        beanNameAutoProxyCreator.setBeanNames("userSe*");
        beanNameAutoProxyCreator.setInterceptorNames("nickelAfterReturningAdvice");
        beanNameAutoProxyCreator.setProxyTargetClass(true);
        return  beanNameAutoProxyCreator;
    }

}

Test.Java配置文件

package com.nq.service;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/29 23:00
 */

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext();
        context.register(AppConfig.class);
        context.refresh();

        UserService userService = (UserService) context.getBean("userService");
        userService.test();
    }
}

Test测试结果
cglib动态代理、jdk动态代理及spring动态代理使用_第7张图片

4.3.3AppConfig另外实现动态代理

package com.nq.service;


import com.nq.advice.NickelAfterReturningAdvice;
import com.nq.advice.NickelBeforeAdvice;
import org.springframework.aop.framework.DefaultAdvisorChainFactory;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.NameMatchMethodPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/28 14:59
 */
@ComponentScan("com.nq")
public class AppConfig {

    @Bean
    public DefaultPointcutAdvisor defaultPointcutAdvisor(){
        NameMatchMethodPointcut pointcut=new NameMatchMethodPointcut();
        pointcut.addMethodName("test");

        DefaultPointcutAdvisor defaultPointcutAdvisor=new DefaultPointcutAdvisor();
        defaultPointcutAdvisor.setPointcut(pointcut);
        defaultPointcutAdvisor.setAdvice(new NickelAfterReturningAdvice());
        return defaultPointcutAdvisor;
    }

    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator();
        return defaultAdvisorAutoProxyCreator;
    }

}

测试结果
cglib动态代理、jdk动态代理及spring动态代理使用_第8张图片
其中DefaultAdvisorAutoProxyCreator通过导入的方式

package com.nq.service;


import com.nq.advice.NickelAfterReturningAdvice;
import com.nq.advice.NickelBeforeAdvice;
import org.springframework.aop.framework.DefaultAdvisorChainFactory;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.NameMatchMethodPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/28 14:59
 */
@ComponentScan("com.nq")
@Import(DefaultAdvisorAutoProxyCreator.class)
public class AppConfig {

    @Bean
    public DefaultPointcutAdvisor defaultPointcutAdvisor(){
        NameMatchMethodPointcut pointcut=new NameMatchMethodPointcut();
        pointcut.addMethodName("test");

        DefaultPointcutAdvisor defaultPointcutAdvisor=new DefaultPointcutAdvisor();
        defaultPointcutAdvisor.setPointcut(pointcut);
        defaultPointcutAdvisor.setAdvice(new NickelAfterReturningAdvice());
        return defaultPointcutAdvisor;
    }
}

cglib动态代理、jdk动态代理及spring动态代理使用_第9张图片

4.4spring中Aspect的使用

创建NickelAspect.java

package com.nq.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/30 2:37
 */
@Aspect
@Component
public class NickelAspect {

    @Before("execution(public void com.nq.service.UserService.test())")
    public void nickelBefore(JoinPoint joinPoint){
        System.out.println("NickelAspect执行了");
    }
}

修改AppConfig.java扫描类

package com.nq.service;


import com.nq.advice.NickelAfterReturningAdvice;
import com.nq.advice.NickelBeforeAdvice;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.framework.DefaultAdvisorChainFactory;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.NameMatchMethodPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/28 14:59
 */
@ComponentScan("com.nq")
@Import(AnnotationAwareAspectJAutoProxyCreator.class)
//@EnableAspectJAutoProxy
public class AppConfig {

}

启动测试类测试
cglib动态代理、jdk动态代理及spring动态代理使用_第10张图片

你可能感兴趣的:(java,spring)