1. 常用注解
- 1.1 @Configuration
- @Configuration
- public class MainConfig {
- }
@Configuration 注解表明这个类是一个配置类, 该类中应该包含如何在 Spring 应用上下文中创建 bean 的细节
- 1.2 @ComponentScan
- @Configuration
- @ComponentScan("per.ym")
- public class MainConfig {
- }
@ComponentScan 注解用于启用组件扫描, 其作用同 xml 中配置 < context:component-scan>. 上述中的配置将会扫描 per.ym 包下的所有类, 若不配置其 value 值, 它会以配置类所在的包作为基础包 (base package) 来扫描组件. 如果你想同时扫描多个包, 可以这样配置:
- @Configuration
- @ComponentScan("per.ym, per.mm")
- public class MainConfig {
- }
在上面的例子中, 所设置的基础包是以 String 类型表示的. 我认为这是可以的, 但这种方法是类型不安全 (not type-safe) 的. 如果你重构代码的话, 那么所指定的基础包可能就会出现错误了. 除了将包设置为简单的 String 类型之外,@ComponentScan 还提供了另外一种方法, 那就是将其指定为包中所包含的类或接口:
- @Configuration
- @ComponentScan(basePackageClasses = {
- MyService.class, MyDao.class
- })
- public class MainConfig {
- }
你可以考虑在包中创建一个用来进行扫描的空标记接口(marker interface). 通过标记接口的方式, 你依然能够保
持对重构友好的接口引用, 但是可以避免引用任何实际的应用程序代码
1.3 @Controller, @Service, @ Repository, @Component
这几个自然不用多说, 算是见得最多的了, 它们锁修饰的类在被 spring 容器扫描到时会被加入到 spring 的管理之中.
@Controller 对应表现层的 Bean
@Service 对应的是业务层 Bean
@Repository 对应数据访问层 Bean
@Component, 当你不能明确的选择上述 3 中, 就用这个
Spring 应用上下文中所有的 bean 都会给定一个 ID, 如果没有明确指定, Spring 会根据类名为其指定一个 ID, 也就是将类名的第一个字母变为小写. 你也可以这样显示的指定一个 ID:
- @Component("ymm")
- public class Person() {
- }
Spring 支持将 @Named(Java 依赖注入规范中所提供的)作为 @Component 注解的替代方案. 两者之间有一些细微的差异, 但是在大多数场景中, 它们是可以互相替换的.
1.4 @Bean
@Bean 注解会告诉 Spring 这个方法将会返回一个对象, 该对象要注册为 Spring 应用上下文中
的 bean. 方法体中包含了最终产生 bean 实例的逻辑.
- @Configuration
- public class MainConifg {
- @Bean
- public BookDao bookDao(){
- return new BookDao();
- }
- }
@Bean 注解会告诉 Spring 这个方法将会返回一个对象, 该对象要注册为 Spring 应用上下文中
的 bean. 方法体中包含了最终产生 bean 实例的逻辑.
默认情况下, bean 的 ID 与带有 @Bean 注解的方法名是一样的. 在上例中, bean 的名字将会是 bookDao. 如果你想为其设置成一个不同的名字的话, 那么可以重命名该方法, 也可以通过 name 属性指定一个不同的名字:
- @Configuration
- public class MainConifg {
- @Bean("ymBookDao")
- public BookDao bookDao(){
- return new BookDao();
- }
- }
还可以像这样设置初始化方法和销毁方法:
- @Configuration
- public class MainConifg {
- @Bean(initMethod = "init", destroyMethod = "destroy")
- public BookDao bookDao(){
- return new BookDao();
- }
- }
这如同在 xml 中配置 init-method="init" destroy-method="destory" 一样
1.5 @Autowired
借助 @Autowired 注解可以实现 spring 的自动装配, 自动装配就是让 Spring 自动满足 bean 依赖的一种方法, 在满足依赖的过程中, 会在 Spring 应用上下文中寻找匹配某个 bean 需求的其他 bean
- @Service
- public class BookService {
- @Autowired(required=false)
- private BookDao bookDao;
- }
你可以把 @Autowired 标注在属性, 构造器, setter 方法上. 实际上, Setter 方法并没有什么特殊之处,@Autowired 注解甚至可以用在类的任何方法上.
除了自带的 @Autowired,spring 还支持 Java 规范中的 @Resource(JSR250)和 @Inject(JSR330), 它们之间的区别如下:
@Autowired:
a, 默认优先按照类型去容器中找对应的组件: applicationContext.getBean(BookDao.class), 如果有且只有一个 bean 匹配依赖需求的话, 那么这个 bean 将会被装配进来; 如果找到多个相同类型的组件, 再将属性的名称作为组件的 id 去容器中查找 applicationContext.getBean("bookDao");
b,@Qualifier("bookDao"): 使用 @Qualifier 明确指定需要装配的组件的 id, 而不是使用属性名;
c, 自动装配默认一定要将属性赋值好, 没有就会报错; 可以使用 @Autowired(required=false);
d,@Primary: 让 Spring 进行自动装配的时候, 默认使用首选的 bean; 也可以使用 @Qualifier 指定需要装配的 bean 的名字;
@Resource:
a, 和 @Autowired 一样实现自动装配功能; 默认是按照组件名称进行装配的;
b, 不支持 @Primary 功能;
c, 不支持 required=false 的功能;
@Inject:
a, 和 @Autowired 一样实现自动装配功能;
b, 不支持 required=false 的功能;
一个可能的例子:
- @Configuration
- @ComponentScan("per.ym.service")
- public class MainConifgOfAutowired {
- @Primary
- @Bean("bookDao1")
- public BookDao bookDao1(){
- BookDao bookDao = new BookDao();
- bookDao.setLable("1");
- return bookDao;
- }
- @Bean("bookDao2")
- public BookDao bookDao2(){
- BookDao bookDao = new BookDao();
- bookDao.setLable("2");
- return bookDao;
- }
- }
- @Service
- public class BookService {
- @Qualifier("bookDao1")
- @Autowired(required=false)
- private BookDao bookDao;
- //@Resource(name="bookDao2")
- //private BookDao bookDao;
- //@Qualifier("bookDao2")
- //@Inject
- //private BookDao bookDao;
- }
- public class BookDao {
- private String lable = "0";
- public String getLable() {
- return lable;
- }
- public void setLable(String lable) {
- this.lable = lable;
- }
- }
- 1.6 @Import
通过导入的方式实现快速给容器中导入组件, 其上可以配置 3 种类型的值, 分别是普通 bean,ImportSelector,ImportBeanDefinitionRegistrar. 特别的, 你可以导入一个被 @Configuration 注解修饰的 bean, 这和在一个 spring 配置文件中使用 < import resource="classpath*:/spring/other.xml" />引入其他配置文件时相似的
- @Configuration
- @Import({
- MainConfig2.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class
- })
- public class MainConfig {
- }
MainConfig2 可以是另一个配置类或者普通的 bean:
- @Configuration
- public class MainConfig2 {
- @Bean
- public Person person(){
- return new Person();
- }
- }
ImportSelector, 其 selectImports 方法返回的数组中应包含要导入容器的 bean 的全类名
- public class MyImportSelector implements ImportSelector {
- // 返回值, 就是到导入到容器中的组件全类名
- //AnnotationMetadata: 当前标注 @Import 注解的类的所有注解信息
- @Override
- public String[] selectImports(AnnotationMetadata importingClassMetadata) {
- // 方法不要返回 null 值, 否则会有 NPE
- return new String[]{"per.ym.bean.Car","per.ym.bean.Dog"};
- }
- }
ImportBeanDefinitionRegistrar, 调用 BeanDefinitionRegistry.registerBeanDefinition 手工注册想要添加到容器中的 bean
- public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
- /**
- * AnnotationMetadata: 当前类的注解信息
- * BeanDefinitionRegistry:BeanDefinition 注册类;
- */
- @Override
- public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
- // 指定 Bean 定义信息
- RootBeanDefinition beanDefinition = new RootBeanDefinition(Red.class);
- // 注册一个 Bean, 指定 bean 名
- registry.registerBeanDefinition("red", beanDefinition);
- }
- }
- 1.7 @Conditional
放在类上, 当满足条件时, 这个类中配置的所有 bean 注册才能生效
放在方法上, 当满足条件时, 才向容器中注册当前 bean
- @Conditional({WindowsCondition.class})
- @Configuration
- public class MainConfig {
- @Conditional(LinuxCondition.class)
- @Bean("linus")
- public Person person(){
- return new Person("linus");
- }
- }
- /**
- * ConditionContext: 判断条件能使用的上下文(环境)
- * AnnotatedTypeMetadata: 注释信息
- */
- // 判断是否 Windows 系统
- public class WindowsCondition implements Condition {
- @Override
- public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
- //1, 能获取到 IoC 使用的 beanfactory
- ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
- //2, 获取类加载器
- ClassLoader classLoader = context.getClassLoader();
- //3, 获取到 bean 定义的注册类
- BeanDefinitionRegistry registry = context.getRegistry();
- //4, 获取当前环境信息
- Environment environment = context.getEnvironment();
- String property = environment.getProperty("os.name");
- if(property.contains("Windows")){
- return true;
- }
- return false;
- }
- }
- 1.8 @Profile
根据当前环境, 动态的激活和切换一系列组件的功能; 指定组件在哪个环境的情况下才能被注册到容器中, 不指定, 任何环境下都能注册这个组件
加了环境标识的 bean, 只有这个环境被激活的时候才能注册到容器中
写在配置类上, 只有是指定的环境的时候, 整个配置类里面的所有配置才能开始生效
- @PropertySource("classpath:/dbconfig.properties")
- @Configuration
- public class MainConfigOfProfile implements EmbeddedValueResolverAware{
- @Value("${db.user}")
- private String user;
- private StringValueResolver valueResolver;
- private String driverClass;
- @Profile("test")
- @Bean("testDataSource")
- public DataSource dataSourceTest(@Value("${db.password}")String pwd) throws Exception{
- ComboPooledDataSource dataSource = new ComboPooledDataSource();
- dataSource.setUser(user);
- dataSource.setPassword(pwd);
- dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
- dataSource.setDriverClass(driverClass);
- return dataSource;
- }
- @Profile("dev")
- @Bean("devDataSource")
- public DataSource dataSourceDev(@Value("${db.password}")String pwd) throws Exception{
- ComboPooledDataSource dataSource = new ComboPooledDataSource();
- dataSource.setUser(user);
- dataSource.setPassword(pwd);
- dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/dev");
- dataSource.setDriverClass(driverClass);
- return dataSource;
- }
- @Profile("prod")
- @Bean("prodDataSource")
- public DataSource dataSourceProd(@Value("${db.password}")String pwd) throws Exception{
- ComboPooledDataSource dataSource = new ComboPooledDataSource();
- dataSource.setUser(user);
- dataSource.setPassword(pwd);
- dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/prod");
- dataSource.setDriverClass(driverClass);
- return dataSource;
- }
- @Override
- public void setEmbeddedValueResolver(StringValueResolver resolver) {
- this.valueResolver = resolver;
- driverClass = valueResolver.resolveStringValue("${db.driverClass}");
- }
- }
- db.properties:
- db.user=root
- db.password=123456
- db.driverClass=com.MySQL.jdbc.Driver
启动命令行中设置环境参数:
-Dspring.profiles.active=test
代码方式设置:
- AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfProfile.class);
- applicationContext.getEnvironment().setActiveProfiles("dev");
来源: http://www.bubuko.com/infodetail-3076368.html