欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring框架学习笔记-基于Java类的配置

程序员文章站 2022-05-25 12:58:17
...

1.使用Java类提供Bean定义信息

普通的POJO只要标注@Configuration注解,就可以为Spring容器提供Bean定义的信息了,每个标注了@Bean的类方法都相当于提供一个Bean的定义信息。

package com.baobaotao.conf;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
//说明这个类可以用于为Spring提供Bean的定义信息
public class AppConf{
	@Bean
	//以下两个方法定义了两个Bean,并提供了Bean的实例化逻辑,Bean的类型由方法返回值类型决定,名称默认和方法名相同,当然也可以通过入参显式指定Bean名称,如@Bean(name="userDao")。直接再@Bean所标注的方法中提供Bean的实例化逻辑
	public UserDao userDao(){
		return new UserDao();
	}
	@Bean
	public LohDao logDao(){
		return new LogDao();
	}
	@Bean
	public LogonService logonService(){
		LogonService logonService=new LogonService();
		//将前面定义的Bean注入到logonService Bean中
		logonService.setLogDao(logDao());
		logonService.setUserDao(userDao());
		return logonService; 
	}
}

userDao()方法和logDao()方法定义了一个UserDao和一个LogDao的Bean,它们的Bean名称分别为userDao和logDao。并且后面又定义了一个logonService Bean,并且注入了前面两个Bean。因此以上的配置和以下的XML配置是等效的:

<bean id="userDao" class="com.baobaotao.anno.UserDao"/>
<bean id="logDao" class="com.baobaotao.anno.LogDao"/>
<bean id="logonService" class="com.baobaotao.conf.LogonService" p:userDao-ref="userDao" p:logDao-ref="logDao"/>

基于Java类的配置方式和基于XML或是基于注解的配置方式相比,前者通过代码的方式更加灵活地实现了Bean的实例化以及Bean的装配,但是后面两者都是通过配置声明的方式,再灵活上稍显不足,但是配置上却更简单一些。
如果Bean在多个@Configuration配置类中定义,如何引用不同配置类中定义的Bean呢?例如,UserDao和LogDao这两个Bean在DaoConfig中定义,而LogonService Bean在Service中定义,
LogonService Bean需要引用DaoConfig中定义的两个Bean:

package com.baobaotao.conf;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuratiom;
@Configuration
public class DaoConfig{
	@Bean
	public UserDao userDao(){
		return new UserDao();
	}
	@Bean
	public LogDao logDao(){
		return new LogDao();
	}
}

由于@Configuration注解类本身已经标注了@Component注解,所以任何标注了@Configuration的类,本身也相当于标注了@Component,即它们可以像普通的Bean一样被注入到其他类当中。DaoConfig标注了@Configuration注解后就成为了一个Bean,它可以被自动注入到ServiceConfig中:

@Configuration
public class ServiceConfig{
	@Autowired
	private DaoConfig daoConfig;
	@Bean
	public LogonService logonService(){
		LogonService logonService=new LogonService();
		logonService.setLogDao(daoConfig.logDao());
		logonService.setUserDao(daoConfig.userDao());
		return logonService;
	}
}

调用daoConfig的logDao()和userDao()方法,就相当于将DaoConfig配置类中定义的Bean注入进来,Spring会对配置类所有标注@Bean的方法进行AOP增强,将对Bean声明周期管理的逻辑植入进来。所以当我们执行daoConfig.logDao()方法时,不是简单地执行DaoConfig类中定义的方法逻辑,而是从Spring容器中返回相应的Bean的单例。换句话说,多次调用daoConfig.logD
ao()方法时,返回的都是Spring容器中相同的Bean。在@Bean处,还可以标注@Scope注解以控制Bean的作用范围。如果在@Bean处标注了@Scope(“prototype”),则每次调用的时候则是一个新的Bean。

public class DaoConfig{
	@Scope("prototype")
	@Bean
	public LogDao logDao(){
		return new LogDao();
	}
}

最后,需要特别注意的是,由于Spring容器会自动对@Configuration的类进行改造,以植入Spring容器对Bean的管理逻辑,所以使用基于Java类的配置必须保证Spring aop类包和CGLIB类包加载到类路径下。

2.使用基于Java类的配置信息启动Spring容器

2.1直接通过@Configuration类启动Spring容器

Spring提供了一个AnnotationConfigApplicationContext类,它能够直接通过标注@Configuration的Java类启动Spring容器:

public class JavaConfigTest{
	public static void main(String[] args){
		ApplicationContext ctx=new AnnotationConfigApplicationContext(AppConf.class);
		LogonService logonService=ctx.getBean(LogonService.class);
		logonService.printHello();
	}
}

通过AnnotationConfigApplicationContext类的构造函数直接传入标注@Configuration的Java类,直接用该类中提供的Bean定义信息启动Spring容器。

2.2 XML配置文件引用@Configuration的配置

标注了@Configuration的配置类本身相当于一个标注了@Component的类,一样也是一个Bean,它可以被Spring的< context:component-scan >扫描到。因此,如果希望将配置类组装到XML配置文件中,通过XML配置文件启动Spring容器,仅需要在XML文件中通过< context:component-scan >扫描到相应的配置类就可以了。

<context:component-scan base-package="com.baobaotao.conf" resource-pattern="AppConf.class"/>

2.3Configuration配置类引用XML配置信息

假设在beans3.xml中定义了两个Bean:

<bean id="userDao" class="com.baobaotao.conf.UserDao"/>
<bean id="logDao" class="com.baobaotao.conf.LogDao"/>

在@Configuration配置类中可以通过@ImportResource引入XML配置文件,在配置类中即可直接通过@Autowired引用XML配置文件中定义的Bean:

@Configuration
@ImportResource("classpath:com/baobaotao/conf/beans3.xml");
public class LogonAppConfig{
	@Bean
	@Autowired
	public LogonService  logonService(UserDao userDao,LogDao logDao){
		LogonService logonService=new LogonService();
		logonService.setUserDao(userDao);
		logonService.setLogDao(logDao);
		return logonService;
	}
}

它完成了两项功能:其一、定义了一个LogonService的Bean;其二,通过方法入参自动注入UserDao和LogDao的Bean,这两个Bean是在XML中定义的。