Spring基于Java类配置Bean(一)

首先,回忆一下JavaBean的三种配置方式:

(1)、基于XML的配置方式;(2)、基于注解的配置方式;(3)、基于Java类的配置方式。

之前可能使用最多的可能就是基于注解的配置方式了,基于XML的配置方式太多臃肿,而Java类的配置方式其实在一定程度上取代了xml的配置方式,特别实在SpringBoot中已经完全采用了Java类的配置方式。Java类的配置方式就是声明一个Java类来配置bean。

下面,开始一个基于Java类配置bean:

1、创建一个实体类:

package spring.createBean.javaClass;

import java.io.Serializable;

/**
 * 用户实体类
 */
public class User implements Serializable {

	private static final long serialVersionUID = 5239414273866570046L;
	
	private String userName;
	
	private String password;
	
	private Long updateTime;

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public Long getUpdateTime() {
		return updateTime;
	}

	public void setUpdateTime(Long updateTime) {
		this.updateTime = updateTime;
	}

	@Override
	public String toString() {
		return "User [userName=" + userName + ", password=" + password + ", updateTime=" + updateTime + "]";
	}
	
}

2、创建DAO层:

package spring.createBean.javaClass;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 *  数据层
 */
public class UserDao {
	public List<User> queryUserList() {
		List<User> list = new ArrayList<User>();
		//模拟数据库
		for (int i = 1; i < 6; i++) {
			User user = new User();
			user.setUserName("userName" + i);
			user.setPassword("password" + i);
			user.setUpdateTime(new Date().getTime());
			list.add(user);
		}
		return list;
		
	}
}

3、声明一个Java类,专用于配置bean:

package spring.createBean.javaClass;

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

@Configuration
@ComponentScan(basePackages="spring.createBean.javaClass")
//或者@ComponentScan(basePackageClasses = UserDao.class)
public class SpringBeansConfig {

	/**
	 * 配置Bean时,在该方法上使用@Bean注解
	 * @return
	 */
	@Bean
	public UserDao getUserDao() {
		return new UserDao();
	}
}

解释下@Configuration,@ComponentScan(basePackages="包路径"),@Bean:

 @Configuration:这个注解其实就是把我们当前的这个类,声明为一个配置文件,它就相当于我们的xml配置文件,跟它的作用是一样的,只不过用类的方式来进行展现;
 @ComponentScan(basePackages="包路径"):这个注解其实就是去扫描我们的包路径,对我们需要扫描的包进行扫描,如果需要扫描多个包,之间用逗号隔开即可;除此之外,还可以指定某一个具体的类,例如:@ComponentScan(basePackageClasses = UserDao.class);
 @Bean:这个注解其实更好理解,它就相当于xml中的<bean>,我们之前通过<bean>标签将它注入到容器中,现在只需要在你所需要注入的资源上面加上@Bean注解,就可以注入到Spring容器中。

4、创建一个业务层:

package spring.createBean.javaClass;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import spring.careteBean.IUserService;

/**
 * 业务层
 */
@Service("userService")
public class UserService implements IUserService{

	@Autowired(required = false)
	private UserDao userDao;

	@Override
	public List<User> queryUserList() {
		if (null != userDao) {
			return userDao.queryUserList();
		}
		return null;
	}
}

解释: @Autowired(required=false)注入注意的问题

(1)@Autowired(required=true):当使用@Autowired直接的时候,其实就是默认使用@Autowired(required=true),此时,该bean必须存在,否则就会注入失败。 当找不到一个匹配的 Bean 时,Spring 容器将抛出 BeanCreationException 异常,并指出必须至少拥有一个匹配的 Bean。

(2)@Autowired(required=false):表示忽略当前要注入的bean,即在注入的过程中,扫描到公共方法中要注入的bean,并未找到,强行注入@Autowired就会注入失败。我们又不能单独的去除改方法,所以我们采取的思想就是有bean就注入,没有就不注入。解决办法就是@Autowired(required=false)。

最后,写一个测试类:

package spring.createBean.javaClass;

import java.util.List;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestJavaClassBean {

	public static void main(String[] args) {

		@SuppressWarnings("resource")
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringBeansConfig.class);
		UserService userService = context.getBean(UserService.class);
		
		List<User> userList = userService.queryUserList();
		if (null != userList) {
			for (User user : userList) {
				System.out.println(user);
			}
		} else {
			System.out.println("userList is null...");
		}
		context.destroy();
	}
}

测试结果:


——————————————————@Autowired与@Qualifier————————————————

 @Autowired默认是按照byType进行注入的,但是当byType方式找到了多个符合的bean,又是怎么处理的?如果发现找到多个bean,则又按照byName方式比对(默认是该类的类名,且首字母是小写),如果还有多个,则报出异常。

解决方案:当创建了多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配,在这种情况下,可以使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱。

 也就是说,当发现有多个相同类型的bean时,仅仅使用@Autowired注释是不行的, 因为@Autowired默认是按照byType进行注入的。此时,要结合@Qualifier注释,按照byName方式进行对比。

package spring.createBean.javaClass;

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

@Configuration
@ComponentScan(basePackages="spring.createBean.javaClass")
//或者@ComponentScan(basePackageClasses = UserDao.class)
public class SpringBeansConfig {

	/**
	 * 配置Bean时,在该方法上使用@Bean注解
	 * @return
	 */
	@Bean(name = "userDao")
	public UserDao getUserDao() {
		return new UserDao();
	}
	
	@Bean(name = "userDaoTemp")
	public UserDao getUserDaoTemp() {
		return new UserDao();
	}
}

package spring.createBean.javaClass;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import spring.careteBean.IUserService;

/**
 * 业务层
 */
@Service("userService")
public class UserService implements IUserService{

	@Autowired(required = false)
	@Qualifier("userDaoTemp")//不要这个注释,其实也可以成功注入的,因为在配置bean时,第一个Bean的名字是“userDao”,而byName的默认name就是首字母小写的类名。
	private UserDao userDao;

	@Override
	public List<User> queryUserList() {
		if (null != userDao) {
			return userDao.queryUserList();
		}
		return null;
	}
}


不仅是采用Java类配置bean,采用xml文件配置bean时,出现了此类情况也是一样的:使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱。

参考:

https://mp.weixin.qq.com/s/1-OkoFpxSbHkLL_37XP1Eg

https://blog.csdn.net/vvhesj/article/details/47661001

https://blog.csdn.net/static_coder/article/details/79580981

http://darkmasky.iteye.com/blog/1129828

Spring学习(二十二) Bean配置的三种方式(XML、注解、Java类)介绍与对比: https://blog.csdn.net/icarus_wang/article/details/51649635

猜你喜欢

转载自blog.csdn.net/jingzi123456789/article/details/80309374