java—为什么使用SpringAOP时属性值为空,但相同的值通过getter工作?

sr4lhrrt  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(556)

我知道代理bean是在使用aop时创建的。我不明白为什么我不能在main方法中直接访问属性?在使用aop时,是否总是必须使用方法来获取值?

package power.sam;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.*;
import river.sam.Ganga;

import javax.inject.Inject;
import java.util.stream.Stream;

@Slf4j
@ComponentScan(basePackages = {"power.sam"})
@EnableAspectJAutoProxy
@Data
public class MyTest {

    Employee emp;

    @Autowired
    MyTest(Employee emp){
        this.emp = emp;
    }

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyTest.class);
        context.registerShutdownHook();
        MyTest bean = (MyTest) context.getBean("myTest");
        log.info("Bean is {}", bean);
        log.info("Bean.Employee via getter is {}", bean.getEmp());
        log.info("Bean.Employee via property is {}", bean.emp);

    }
}

输出
14:51:12.925[main]info power.sam.mytest-bean是mytest(emp=power.sam。employee@3700ec9c)
14:51:12.955[main]info power.sam.mytest-bean.employee通过get is power.sam。employee@3700ec9c
14:51:12.955[main]info power.sam.mytest-bean.employee via属性为空
更新:这似乎只发生在我有一个所有方法的建议,如

@Before("execution(public * *(..))")
fd3cxomn

fd3cxomn1#

为了弄清楚在后台发生了什么,在测试代码中添加以下内容。

System.out.println("Bean.Employee runtime class is "+ bean.getClass());

完整的主要方法如下

public static void main(String[] args) throws Exception {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyTest.class);
    context.registerShutdownHook();
    MyTest bean = (MyTest) context.getBean("myTest");
    System.out.println("Bean is "+ bean);
    System.out.println("Bean.Employee via getter is "+ bean.getEmp());
    System.out.println("Bean.Employee runtime class is "+ bean.getClass());
    System.out.println("Bean.Employee via property is "+ bean.emp);
}

现在使用切入点表达式运行时: @Before("execution(public * *(..))") 控制台日志是

Bean is rg.so.qn64919052.MyTest@662f5666
Bean.Employee via getter is rg.so.qn64919052.entity.Employee@75ed9710
Bean.Employee runtime class is class rg.so.qn64919052.MyTest$$EnhancerBySpringCGLIB$$6e53892a
Bean.Employee via property is null

注:以下为 bean.getClass() 返回创建的代理对象的类。
为了清晰起见, Employee 类是在包中创建的 rg.so.qn64919052.entity 现在使用切入点表达式运行时: @Before("execution(public * rg.so.qn64919052.entity.Employee.*(..))") 控制台日志是

Bean is rg.so.qn64919052.MyTest@acdb094
Bean.Employee via getter is rg.so.qn64919052.entity.Employee@674bd420
Bean.Employee runtime class is class rg.so.qn64919052.MyTest
Bean.Employee via property is rg.so.qn64919052.entity.Employee@674bd420

注:以下为 bean.getClass() 返回原始类。
说明:
springaop是基于代理的。动态代理只继承方法,不继承任何示例变量。
第一次运行的切入点表达式有一个全局作用域,它将通知所有springbean的public(protected和package作用域,因为cglib)方法执行。因此,为mytest创建了一个代理。
第二次运行中的切入点表达式的作用域有限( rg.so.qn64919052.entity.Employee.* )我的测试没有代理。
参考文献:
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop-介绍代理。

相关问题