spring的java配置方式以及注入时的注意点

Java配置是Spring4.x推荐的配置方式,可以完全替代xml配置。

通过两个注解@Configuration和@Bean来实现。

1、@Configuration作用于类上,可以理解为一个xml配置文件。

2、@Bean作用于方法上,可以理解为xml配置中的<bean>。

@Configuration
@ComponentScan("com.xw.test")
public class SpringConfig {
	@Bean
	public UserDao getUserDao() {
		return new UserDaoImpl();
	}
}

@Bean注解会自动把方法的名字设置为bean的名字,如上面的就会设置为getUserDao

public static void main(String[] args) {
	AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
	UserDao userDao1 = (UserDao) context.getBean("getUserDao");
	System.out.println(userDao1);
	context.destroy();
}

@ComponentScan("com.xw.test")的作用:扫描包


在使用注解的方式时,必须配置

<context:annotation-config/>

作用:向 Spring 容器注册这 4 个BeanPostProcessor

AutowiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
PersistenceAnnotationBeanPostProcessor
RequiredAnnotationBeanPostProcessor

使用@Autowired注解,就必须事先在Spring容器中声明AutowiredAnnotationBeanPostProcessor。
使用@Resource 、@PostConstruct、@PreDestroy等注解就必须声明CommonAnnotationBeanPostProcessor。
使用@PersistenceContext注解,就必须声明PersistenceAnnotationBeanPostProcessor。

使用@Required的注解,就必须声明RequiredAnnotationBeanPostProcessor。

但是:<context:component-scan base-package=XX.XX/>包含了自动注入上述processor的功能。所以就不用写了。


@Autowired和@Resource的区别

使用@Autowired时,先在容器中查询类型的bean(byType)
1、如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据。

2、如果查询的结果不止一个,那么@Autowired会根据名称来查找。

名称:是指的如下userDao这个名称,或者自己通过注解@Qualifier("getUserDao")来指定名称查找。

@Autowired

private UserDao userDao;

3、如果根据名称查询的结果为空,那么会抛出异常。解决方法时,使用required=false。

所以在使用的时候我们一般是在实现类中加@Service、@Repository,名字是默认的,如

@Repository

public class UserDaoImpl implements UserDao 
如上面这种,名称就是类首字母小写userDaoImpl。

注意:像上面的例子,如果有多个实现类UserDaoImpl UserDaoImpl2,根据上面@Autowired的规则,根据类型查找的结果不止一个,且根据名称userDao来查找肯定也不匹配(一个是userDaoImpl,一个是userDaoImpl2),此时就像上面第三步一样,抛出异常,注入失败。此时就可以用@Qualifier("userDaoImpl")来区分。

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.xw.test.UserDao' available: expected single matching bean but found 2: userDaoImpl,userDaoImpl2

使用@Resource时,是根据名字来查找,如下:

@Resource
private UserDao userDao;

 1、先查找是否有名称为userDao的bean。

 2、如果没有找到,则看是否有name属性(@Resource  name=“”),有则根据name查找。

 3、如果还没有找到,则根据类型来查找,如果没有找到或者找到多个则抛出异常。


疑惑:

第一种情况:一个在类上@Repository,一个在标有@Configuration类的方法上。

@Repository("userDaoImpl")
public class UserDaoImpl implements UserDao {
@Bean("userDaoImpl")
public UserDao getUserDao2() {
	return new UserDaoImpl2();
}
信息: Overriding bean definition for bean 'userDaoImpl' with a different definition: replacing [Generic bean: class [com.xw.test.UserDaoImpl];

这样是可以共存的,会有个如上Overriding的提示而已。

第二种情况:两个都在类上@Repository

@Repository("userDaoImpl")
public class UserDaoImpl implements UserDao {
@Repository("userDaoImpl")
public class UserDaoImpl2 implements UserDao {
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.xw.test.SpringConfig]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'userDaoImpl' for bean class [com.xw.test.UserDaoImpl2] conflicts with existing, non-compatible bean definition of same name and class [com.xw.test.UserDaoImpl]
此时初始化报错。

两种情况都是注入两个名字一样的不同属于不同类的实例对象,但结果不一样。猜测:和@Configuration有关,有时间再看下源码。


读取外部参数:通过注解@PropertySource("classpath:test.properties")读取指定的配置。

使用参数:

常用的方式一:通过@Value

@Value("${name}")
private String name;
@Value("${age}")
private String age;

常用的方式二:通过Environment

@Autowired
private Environment enviroment;
enviroment.getProperty("name")即可获取。

借此温习记录下spring的注解。


猜你喜欢

转载自blog.csdn.net/ch_show/article/details/80414849