spring动态代理

反射机制


1、Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。
2、Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。
反射的用途:
1、反编译:.class-->.java
2、通过反射机制访问java对象的属性,方法,构造方法等
3、当我们在使用IDE,比如Ecplise时,当我们输入一个对象或者类,并想调用他的属性和方法是,一按点号,编译器就会自动列出他的属性或者方法,这里就是用到反射。
4、反射最重要的用途就是开发各种通用框架。比如很多框架(Spring)都是配置化的(比如通过XML文件配置Bean),为了保证框架的通用性,他们可能需要根据配置文件加载不同的类或者对象,调用不同的方法,这个时候就必须使用到反射了,运行时动态加载需要的加载的对象。
反射的基本使用:
1、获得Class:主要有三种方法:
(1)Object-->getClass
(2)任何数据类型(包括基本的数据类型)都有一个“静态”的class属性
(3)通过class类的静态方法:forName(String className)(最常用)
Class stuClass3 = Class.forName("fanshe.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
有点那种感觉,反射就是获取反编译的.Java文件

静动态代理区分理解


首先,我们定义一个服务接口 UserService,其中包含一个方法 getUser:

public interface UserService {
    String getUser();
}

然后,有一个实现了该接口的服务类 UserServiceImpl:

public class UserServiceImpl implements UserService {
    @Override
    public String getUser() {
        return "User from UserServiceImpl";
    }
}

接下来,创建一个静态代理类 UserServiceStaticProxy,用于代理 UserServiceImpl 类的方法调用,并在调用前后添加额外的逻辑:

public class UserServiceStaticProxy implements UserService {

    private UserService userService;

    public UserServiceStaticProxy(UserService userService) {
        this.userService = userService;
    }
    // 静态代理类需要实现目标类的方法
    @Override
    public String getUser() {
        System.out.println("Static Proxy: Before invoking getUser method");
        String result = userService.getUser();
        System.out.println("Static Proxy: After invoking getUser method");
        return result;
    }
}

然后,创建一个动态代理类 UserServiceDynamicProxy,利用 Spring 提供的 ProxyFactoryBean 来创建动态代理:

import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactoryBean;

import java.lang.reflect.Method;
// 动态代理需要实现动态代理的接口,这里的区别就于动是实现jdk已经写好的代理类,而静是实现目标代理类
public class UserServiceDynamicProxy implements MethodBeforeAdvice {

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("Dynamic Proxy: Before invoking " + method.getName() + " method");
    }

    public UserService createProxy(UserService target) {
        ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
        proxyFactoryBean.setInterfaces(UserService.class);
        proxyFactoryBean.setTarget(target);
        proxyFactoryBean.addAdvice(this);
        return (UserService) proxyFactoryBean.getObject();
    }
}

在这个动态代理类中,我们实现了 Spring 的 MethodBeforeAdvice 接口,用于在目标方法执行前执行额外逻辑。然后,通过 ProxyFactoryBean 创建动态代理对象。
接下来,我们使用 Spring 进行配置和使用:

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {

    @Bean
    public UserService userService() {
        return new UserServiceImpl();
    }

    @Bean
    public UserService userServiceStaticProxy(UserService userService) {
        return new UserServiceStaticProxy(userService);
    }

    @Bean
    public UserServiceDynamicProxy userServiceDynamicProxy() {
        return new UserServiceDynamicProxy();
    }

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

        // 静态代理
        UserService staticProxy = context.getBean("userServiceStaticProxy", UserService.class);
        staticProxy.getUser();

        // 动态代理
        UserServiceDynamicProxy dynamicProxy = context.getBean(UserServiceDynamicProxy.class);
        UserService dynamicProxyTarget = context.getBean(UserService.class);
        UserService dynamicProxyInstance = dynamicProxy.createProxy(dynamicProxyTarget);
        dynamicProxyInstance.getUser();

        context.close();
    }
}

在这个配置中,我们定义了三个 Bean:userService、userServiceStaticProxy、userServiceDynamicProxy。其中 userService 是原始的服务对象,userServiceStaticProxy 是静态代理对象,userServiceDynamicProxy 是动态代理对象。在 main 方法中,我们分别使用静态代理和动态代理来调用服务方法。
在这个例子中,UserServiceStaticProxy 是静态代理类,它实现了 UserService 接口,并在其中包含了原始服务对象的引用。而 UserServiceDynamicProxy 则是动态代理类,它利用 Spring 提供的 ProxyFactoryBean 来创建动态代理对象,实现了动态代理的功能。

动态代理核心

InvocationHandler接口和Proxy类,InvocationHandler通过invoke()方 法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用InvocationHandler动态创建一个符合某一接口的的实例,生成目标类的代理对象。

JDK动态代理和CGLIB动态代理: JDK动态代理只提供接口的代理,不支持类的代理。CGLIB动态代理支持类的代理

动态代理注解

1.@Aspect
位置:类上方
作用:声明当前类为切面类
2.@Pointcut
位置:方法上方
作用:指定切入点
3.@Before
位置:方法上方
作用:标注当前方法作为前置通知
4.@After
位置:方法上方
作用:标注当前方法作为后置通知
5.@AfterReturning
位置:方法上方
作用:标注当前方法作为返回后通知
6.@AfterThrowing
位置:方法上方
作用:标注当前方法作为异常后通知
7.@Around
位置:方法上方
作用:标注当前方法作为环绕通知

  • 15
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值