Java Spring:proxyMode = ScopedProxyMode.TARGET_CLASS同一个对象有不同的属性怎么可能?

时间:2017-10-07 18:54:47

标签: java spring

请查看以下代码:

@Component
@Scope(value= ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class JdbcConnection {

    public JdbcConnection() {
        System.out.println("JDBC Connection");
    }
}


@Component
public class PersonDAO {
    @Autowired
    JdbcConnection jdbcConnection;

    public JdbcConnection getJdbcConnection() {
        return jdbcConnection;
    }

    public void setJdbcConnection(JdbcConnection jdbcConnection) {
        this.jdbcConnection = jdbcConnection;
    }
}

@SpringBootApplication
public class SpringIn5StepsApplication {

    private static org.slf4j.Logger LOGGER = LoggerFactory.getLogger(SpringIn5StepsApplication.class);

    public static void main(String[] args) {
        ApplicationContext applicationContext = SpringApplication.run(SpringIn5StepsApplication.class, args);
        PersonDAO personDao = applicationContext.getBean(PersonDAO.class);
        PersonDAO personDao2 = applicationContext.getBean(PersonDAO.class);

        LOGGER.info("{}", personDao);
        LOGGER.info("{}", personDao.getJdbcConnection());

        LOGGER.info("{}", personDao2);
        LOGGER.info("{}", personDao2.getJdbcConnection());
    }
}

运行我们在控制台中获取的代码时:

  

:com.spring.basics.springin5steps.scope.PersonDAO@352c1b98:   com.spring.basics.springin5steps.scope.JdbcConnection@41005828:   com.spring.basics.springin5steps.scope.PersonDAO@352c1b98:   com.spring.basics.springin5steps.scope.JdbcConnection@60b4beb4

这意味着personDao和personDao2基本上是同一个对象。如果是这样,从对象personDao获取属性jdbcConnection后,我们得到两个不同的对象怎么可能?

1 个答案:

答案 0 :(得分:1)

您使用的是ScopedProxyMode.TARGET_CLASSConfigurableBeanFactory.SCOPE_PROTOTYPE

因此,spring会生成基于cglib的代理并将其注入您的PersonDAO类。 每个方法调用的代理使用新的JdbcConnection(因为范围是prototype)并委托方法调用它。

当您打印JdbcConnection时,隐式调用导致toString()创建new JdbcConnection()的{​​{1}},将调用toString()方法。

  

如果是这样,从对象personDao获取属性jdbcConnection后,我们得到两个不同的对象怎么可能?

不,你有相同的对象,但是在不同的对象上调用了toString()方法。试试这个:

JdbcConnection connection1 = dao.getJdbcConnection();
JdbcConnection connection2 = dao.getJdbcConnection();
System.out.println("connection1 == connection2: " + (connection1 == connection2));

输出:

  

connection1 == connection2:true