spring bean的配置方式:xml、@Component、
1 曾经的王者-xml
以我们常说的Service和DAO为例:
// UserDAOImpl.java
public class UserDAOImpl implements UserDAO {
}
// UserServiceImpl.java
public class UserServiceImpl implements UserService {
private UserDAO userDAO;
}
我们使用xml配置两个bean,以及其需要的依赖:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDAO" class="demo.dao.UserDAOImpl" />
<bean id="userService" class="demo.service.UserServiceImpl">
<property name="userDAO" ref="userDAO" />
</bean>
</beans>
2. 横空出世-Java注解(@Component)
这时候的bean我们更喜欢使用@Component
、@Repository
、@Service
这样的注解进行配置,依赖则使用@Autowired
、@Resource
;然后xml指明一下要扫描的包即可。
// UserDAOImpl.java
package demo.dao;
@Repository
public class UserDAOImpl implements UserDAO {
}
-----------------------
// UserServiceImpl.java
package demo.service;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDAO userDAO;
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="demo" />
</beans>
注:
@Repository
、@Service
等可以看成是继承@Component
的注解,在spring容器中,除了被注册成一个bean,除了更加语义化之外(比如@Repository
表示操作持久层的bean,@Service
表示操作业务逻辑的bean),似乎没有表现出其他特别的用处(或许将来会有额外的表现)。
3. @Configuration 配置类的到来
从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被ApplicationContext进行扫描,并用于构建bean定义,初始化Spring容器。
3.1 @Bean
仍以UserDAO和UserService为例:
// UserDAOImpl.java
public class UserDAOImpl implements UserDAO {
}
// UserServiceImpl.java
public class UserServiceImpl implements UserService {
private UserDAO userDAO;
}
我们使用@Configuration进行配置的话:
@Configuration
public class UserBeanConfig {
@Bean(name = "userDAO")
public UserDAO userDAO() {
return new UserDAOImpl();
}
@Bean(name = "userService")
public UserService userService(@Qualifier("userDAO") UserDAO userDAO) {
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDAO(userDAO);
return userService;
}
}
关于@Configuration
,可以理解成与<beans>
标签对应;@Bean
则是与<bean>
标签对应。可以确定的是,xml能干的事情,配置类基本上都能干。
注:这里只是为了展示@Configuration与@Bean的功能,真实项目中业务代码的Bean很少会有人这么玩,@Component与@Autowire仍是最受欢迎的注解。
3.2 @ComponentScan
若UserDAOImpl、UserServiceImpl继续使用注解(@Component
、@Autowire
),扫描的方式,除了xml中的<context:component-scan base-package="demo" />
,还可以使用@Configuration
+@ComponentScan
,
package demo.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("demo")
public class UserBeanConfig {
}
如果不指定扫描的包,则是扫描配置类下对应的包(本例是demo.config)。
3.3 SpringBoot中的扫描
大家都知道,一个简单的SpringBoot配置非常简洁:
package demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
关于@SpringBootApplication注解:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
public @interface SpringBootApplication {
...
}
其中的@SpringBootConfiguration:
@Configuration
public @interface SpringBootConfiguration {
}
我们看到,@SpringBootApplication
其实非常的简单:
@SpringBootApplication
=@Configuration
+@ComponentScan
+@EnableAutoConfiguration
启动类DemoApplication可以看成是:一个普通的@Configuration配置类+main函数的执行类。main入口进去后,第一个拿到的配置类就是这个,而这是一切的开始。
值得注意的是:@SpringBootApplication
中的@ComponentScan
其实是没有指定要扫描的包名的,会默认扫描启动类下的包(本例是demo),这也是为什么启动类通常放顶层包下,类似这样的结构: