Spring升级案例之IOC介绍和依赖注入 (2)

为了更加清楚地看到这两个接口之间的区别,我们在AccountDaoImpl和AccountServiceImpl类的无参构造方法中添加如下内容:

//AccountDaoImpl public AccountDaoImpl() { System.out.println("dao创建了"); } //AccountServiceImpl public AccountServiceImpl() { System.out.println("service创建了"); }

对ui.Client类中的main方法添加如下代码:

Resource resource = new ClassPathResource("beans.xml"); BeanFactory factory = new DefaultListableBeanFactory(); BeanDefinitionReader bdr = new XmlBeanDefinitionReader((BeanDefinitionRegistry) factory); bdr.loadBeanDefinitions(resource); System.out.println(factory.getBean("accountDao"));

采用断点调试,我们可以发现:

对于ApplicationContext来说,执行ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");之后,立刻就会输出“service创建了”和“dao创建了”。

而对于BeanFactory来说,只有当执行到System.out.println(factory.getBean("accountDao"));之后,才会输出“dao创建了”。

这也就说明ApplicationContext是立即加载,BeanFactory是延迟加载。通常而言,ApplicationContext接口更加常用。此外,我们也可以自己指定单例模式还是多例模式。

三、Bean对象的管理细节 1.三种创建bean对象的方式

第一种方式:使用默认构造方法创建

在Spring配置文件中使用bean标签,如果只有id和class属性,就会使用默认构造方法(无参构造方法)创建对象。如果没有默认构造方法,则对象无法创建。例如,之前我们所使用的便是这第一种方式。

<bean></bean>

第二种方式:使用其他类(比如工厂类)中的方法创建对象,并存入Spring容器,该类可能是jar包中的类,无法通过修改源码来提供默认构造方法。

为了演示,我们在src/main/java目录新建factory包,在factory包下新建类InstanceFactory:

public class InstanceFactory { //非静态方法 public IAccountService getAccountService() { return new AccountServiceImpl(); } }

instanceFactory对应的就是factory包下的InstanceFactory类的对象,accountService对应的是InstanceFactory类下的getAccountService方法返回的对象。factory-bean属性用于指定创建本次对象的factory,factory-method属性用于指定创建本次对象的factory中的方法。

<bean></bean> <bean factory-bean="instanceFactory" factory-method= "getAccountService"></bean>

第三种方式:使用其他类(比如工厂类)中的静态方法创建对象,并存入Spring容器,该类可能是jar包中的类,无法通过修改源码来提供默认构造方法。

为了演示,我们在src/main/java目录新建factory包,在factory包下新建类StaticFactory:

public class StaticFactory { //静态方法 public static IAccountService getAccountService() { return new AccountServiceImpl(); } }

由于是静态方法,所以无需指定factory-bean属性。class属性指定创建bean对象的工厂类,factory-method方法指定创建bean对象的工厂类中的静态方法。

<bean factory-method="getAccountService"></bean>

2.bean对象的作用范围

bean标签的scope属性(用于指定bean对象的作用范围),有如下取值:常用的就是单例和多例

singleton:单例(默认值)

prototype:多例

request:作用域Web的请求范围

session:作用于Web的会话范围

global-session:作用于集群的会话范围(全局会话范围),当不是集群环境时,它就是session

这里我们演示单例和多例:

<bean scope="singleton"></bean> <bean scope="prototype"></bean>

此时即便Client类中的main方法使用ApplicationContext接口:

public static void main(String[] args) { //1.获取IoC核心容器 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); //2.根据id获取bean对象 //第一种方法:只传入id获取到对象之后强转为需要的类型 IAccountService accountService = (IAccountService) applicationContext.getBean("accountService"); System.out.println(accountService); //第二种方法:传入id和所需要类型的字节码,这样getBean返回的对象就已经是所需要的对象 IAccountDao accountDao = applicationContext.getBean("accountDao", IAccountDao.class); IAccountDao accountDao1 = (IAccountDao) applicationContext.getBean("accountDao"); System.out.println(accountDao == accountDao1); }

使用断点调试,我们可以发现:

在执行到ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");时,就会输出“service创建了”,不会输出“dao创建了”。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyspyd.html