您的位置:首页 > 编程语言 > Java开发

Spring 常用注解解析

2019-05-30 00:41 3503 查看

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");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: