重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
1.1 @Configuration
创新互联坚持“要么做到,要么别承诺”的工作理念,服务领域包括:成都做网站、网站建设、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的衡阳网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!
@Configuration
public class MainConfig {
}
@Configuration注解表明这个类是一个配置类,该类中应该包含如何在Spring应用上下文中创建bean的细节
1.2 @ComponentScan
@Configuration
@ComponentScan("per.ym")
public class MainConfig {
}
@ComponentScan注解用于启用组件扫描,其作用同xml中配置
@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配置文件中使用
@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");