配置类
使用JavaConfig代替xml配置文件 配置类 == 配置文件
声明为配置类的java类需要加上@Configuration注解
使用@Bean为容器添加一个bean,返回类型是bean的类型,相当于xml中的class,返回值为实际添加到ioc中的对象,默认id是第一个之母小写的方法名,可以指定id值
@Configuration
public class Spring_anno_PropertiesValue {
@Bean
public Person person1(){
return new Person();
}
}
使用配置类初始化容器只要把ClassPathXmlApplicationContext()改为AnnotationConfigApplicationContext即可
ApplicationContext config = new AnnotationConfigApplicationContext(Spring_anno_Profile.class);
ServiceTest serviceTest = (ServiceTest) config.getBean("serviceTest");
serviceTest.test();
组件扫描
使用组件扫描需要添加@ConponentScan注解
basePackages指定扫描的包,可以使用过滤器排除或添加指定的组件
excludeFilters需要排除的包,可指定排除规则
*FilterType.annotatioon: 按照注解
*FilterType.ASSIGNABLE_TYPE: 按照给定的类型
*FilterType.ASPECTJ。使用ASPECTJ表达式
*FilterType.REGEX; 使用正则表达式
*FilterType.CUSTOM. 使用自定义表达式,写TypeFilter的实现类
includeFilters,指定扫描时需要添加的组件
要使上两个配置生效要禁用默认过滤器,useDefaultFilters = false
可以使用conponentscans 指定多个扫描器
@ComponentScans(value = {
@ComponentScan(value = "service",excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = {Controller.class, Repository.class})},useDefaultFilters = false)
})
其中FilterType.CUSTOM 使用自定义过滤规则需要实现TypeFilter接口
public class MyTypeFilter implements TypeFilter {
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获取当前注解的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前资源(类的路径)
Resource resource = metadataReader.getResource();
System.out.println("---"+classMetadata.getClassName());
if (classMetadata.getClassName().contains("sadf")){
//添加
return true;
}
//排除
return false;
}
}
然后将其加入到filter即可
@ComponentScan(value = "service",excludeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})})
}
生命周期 @Scope(“xxx”)
//指定生命周期
/*
* @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
* @see ConfigurableBeanFactory#SCOPE_SINGLETON
* @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
* @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
* singleton: 单实例的(默认值),ioc容器启动会调用方法创建对象放到ioc容器中,以后每次获取就直接从容器中获取值
* prototype: 多实例的, 每次获取时,才调用方法创建对象
* request:同一个请求创建一个实例
* session:同一个session创建一个实例
*/
懒加载 @Lazy
/*
*懒加载
* 单实例bean:默认在容器启动时创建对象
* 懒加载:容器启动时不创建对象,第一次使用(获取)bean创建对象,并初始化
*/
条件加载@Conditional
/*
*条件加载
* @Conditional:按照一定的条件进行判断,满足条件给容器中注册bean, 参数是condition数组
* 当注解放在类上,当满足条件时,这个类中配置的所有bean注册才能生效
*/
使用条件加载需要指定一个实现Condition接口的类
public class LinuxCondition implements Condition {
/**
*
* @param context: 判断条件能使用的上下文条件(环境)
* @param metadata: 注释信息
* @return
*/
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//1.能获取到ioc 使用的beanfactory
//ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//2.能获取类加载器
//ClassLoader classLoader = context.getClassLoader();
//3.能获取当前环境信息
Environment environment = context.getEnvironment();
//4.能获取bean定义的注册类
//BeanDefinitionRegistry registry = context.getRegistry();
String property = environment.getProperty("os.name");
if (property.contains("linux")){
return true;
}
return false;
}
}
@import: 快速给容器添加一个组件
//使用@import注解快速的给容器导入一个组件
//在类上使用
// -1.@Import({要导入到容器中的组件});容器就会自动注册这个组件,id默认是全类名
// -2 @Import({ImportSelector.class}):返回需要导入的组件的全类名数组(实现ImportSelector接口)
// -3 ImportBeanDefinitionRegister:
1.直接导入
@Import({ImportBean01.class})
2.实现importSelector接口
//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector {
/**
* 返回值;就是导入到容器中的组件的全类名
* @param importingClassMetadata:当前标注@import注解的类的全部注解信息
* @return
*/
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"config.bean.ImportSelectorBean01","config.bean.ImportSelectorBean02"};
}
}
然后将其添加到注解中@Import({MyImportSelector.class})
3.使用ImportBeanDefinitionRegister,需要实现ImportBeanDefinitionRegistrar接口
public class MyImportBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {
/**
*
* @param importingClassMetadata: 当前类的注释信息
* @param registry : BeanDefinition注册类。把所有需要添加到容器中的bean;用registry的registerBeanDefinition方法添加
*/
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean bean01 = registry.containsBeanDefinition("config.bean.ImportBean01");
boolean bean02 = registry.containsBeanDefinition("config.bean.ImportBean02");
if (bean01 && bean02){
RootBeanDefinition beanDefinition = new RootBeanDefinition(RegistrarBean01.class);
registry.registerBeanDefinition("registryBean",beanDefinition);
}
}
}
自动装配
/**
* @Autowired;
* @Qualifire;
* @Primary;在@Bean配合使用指定自动装配的高优先级
*
* Spring还支持使用@Resource(JSR250)和@Inject(JSR330)【java规范的注解】
* @Resource;可以和@Autowired一样实现自动装配功能;默认按照变量名进行装配;name指定bean的id
* @Inject:需要导入依赖
*、
* 自定义组件想要使用Spring容器底层的一些组件(ApplicationContext。BeanFactory。xxx)
* 需要实现xxxAware接口;在创建对象时,会调用接口规定的方法注入相关组件;
*/
生命周期
bean的生命周期
bean的创建 – 初始化 – 销毁的过程
容器管理bean的生命周期
我们可以自定义初始化和销毁方法,容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法
- 1.指定初始化方法和销毁方法:
-
xml:init-method和destory-method
- 2.initializingBean和disposableBean
- 3.可以使用JSR250
-
@PostConstruct;在bean创建完成并且属性赋值完成,来执行初始化方法
-
@PreDestory; 在bean销毁之前调用这个方法
- 4.BeanPostProcessor接口:bean的后置处理器
-
在bean初始化前后进行一些处理工作
-
postProcessBeforeInitialization:在初始化之前操作
-
postProcessAfterInitialization:在初始化之后操作
@Bean(value = "lifeBean",initMethod = "init",destroyMethod = "destory")
//或在方法中添加对应注解
// @PostConstruct
// @PreDestroy
使用@Value赋值
//使用@Value赋值
//1.基本数值
//2.可以写SpEL:#{}
//3.可以写${};取出配置文件的值(在运行环境)
@Value("张三")
private String name;
@Value("#{20-2}")
private Integer age;
@Value("${address}")
private String address;
要取出配置文件的内容需要在配置类中添加注解@PropertySource(“classpath:Spring.Properties”)导入指定的配置文件内容
配置文件的动态激活
Profile: Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能
- @Profile:指定组件在那种情况下才能被注册到容器中;不指定任何环境都能注册这个组件;
//可以标记在类和方法上
@PropertySource("classpath:/dbConfig.properties")
@Configuration
@ComponentScan("service")
@EnableAspectJAutoProxy
public class Spring_anno_Profile {
@Value("${user}")
String user;
@Value("${password}")
String password;
@Value("${driver}")
String driver;
@Profile("test")
@Bean
public DataSource dataSourceTest(@Value("url_Test") String url){
ComboPooledDataSource dataSource = new ComboPooledDataSource();
System.out.println("test");
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setJdbcUrl(url);
try {
dataSource.setDriverClass(driver);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return dataSource;
}
@Profile("dev")
@Bean
public DataSource dataSourceDev(@Value("url_Dev") String url){
ComboPooledDataSource dataSource = new ComboPooledDataSource();
System.out.println("dev");
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setJdbcUrl(url);
try {
dataSource.setDriverClass(driver);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return dataSource;
}
@Profile("prod")
@Bean
public DataSource dataSourceProd(@Value("url_Prod")String url){
ComboPooledDataSource dataSource = new ComboPooledDataSource();
System.out.println("prod");
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setJdbcUrl(url);
try {
dataSource.setDriverClass(driver);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return dataSource;
}
}
激活方式有以下两种:
1.通过命令行激活:-Dspring.profiles.active=test
2.创建一个空参的容器
-
AnnotationConfigApplicationContext config = new AnnotationConfigApplicationContext();
设置环境
-
config.getEnvironment().setActiveProfiles("test");
注册主配置类
-
config.register(Spring_anno_Profile.class);
/刷新容器
-
config.refresh();
容器只会添加与profile匹配的bean(当@profile修饰类时,添加的是该配置类)