作用在类上,表名被@Configuration修饰的类是一个配置类。主要与@Bean联合使用将第三方jar类注入到容器中
@Configuration
public class MyConfig {
主要与@Configuration注解联合使用,作用在方法上,将方法返回的类注入到容器中。注入容器中的Bean Id 默认为方法名.
主要属性:
name 同 value: 用于自定义注入容器中Bean的Id;是一个数组,可以为这个bean定义多个id
@Bean(name = {"c1","c2"})
public C c(){
initMethod: 指定初始化方法
destroyMethod:指定Bean的清除方法
3.@ComponentScan
指定需要扫描的包,将标有@Component,@Repository,@Service,@Controller等注解的类注入到容器中
主要属性:
basePackages 同 value 指定需要扫描的包,可以指定多个
basePackageClasses:指定扫描的类
excludeFilters:根据type,classes指定不扫描的类,默认根据注解方式进行排除
@ComponentScan(basePackages = {"com.java"},
excludeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION,
classes={Controller.class}) })
includeFilters:根据type,classes指定需要被包含的类,必须使用useDefaultFilters=false,因为@ComponentScan默认扫描@Component,@Repository,@Service,@Controller等注解
@ComponentScan(value = "com.java", useDefaultFilters=false,
includeFilters={ @ComponentScan.Filter(type = FilterType.ANNOTATION,
classes={Controller.class} )
Filter的type类型:
FilterType.ASSIGNABLE_TYPE 可以指定类类型
@ComponentScan(basePackages = {"main.java.com.myAnnotation"},
includeFilters = { @ComponentScan.Filter(type= FilterType.ASSIGNABLE_TYPE,
classes = {AliController.class}) },
useDefaultFilters = false)
FilterType.CUSTOM 可以自定义类型,将AliFilter中满足条件的Bean注入到容器中
@ComponentScan( basePackages = {"main.java.com.myAnnotation"},
includeFilters = { @ComponentScan.Filter(type=FilterType.CUSTOM,
classes = {AliFilter.class}) },
useDefaultFilters = false )
public class AliFilter implements TypeFilter {
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
ClassMetadata classMetadata = metadataReader.getClassMetadata();
if(classMetadata.getClassName().equals("main.java.com.myAnnotation.service.CustomService")
{
return true;
}
return false;
}
}
4.@ComponentScans
配置多个@ComponentScan规则
@ComponentScans(
value= {
@ComponentScan(value = "com.java",
useDefaultFilters=false,
includeFilters={ @ComponentScan.Filter(type = FilterType.ANNOTATION,
classes={Controller.class} ) })
}
)
5.@Scope 决定Bean创建实例的方式
属性:
scopeName 同 value:
singleton: 单实例的(默认),容器启动时就会注入到容器中,立即加载
prototype:多实例的,只有当每次调用/获取的时候才会注入到容器中,延迟加载
request: 每次request请求都会生成一个实例
session:每一个session生成一个实例
@Scope(scopeName = "prototype")
@Bean
public Java java(){
6.@Lazy 在单实例的情况下,决定实例是否延迟加载
当容器启动时,不会立即注入到容器中,只有当从容器获取的时候才会出入到容器中.
@Lazy
@Scope(scopeName = "singleton")
@Bean
public Java java(){
7.@Conditional 被标有该注解的类/方法,只有满足条件才回注入/执行
@Conditional({MyCondition.class})
@Bean
public Java java(){
public class MyCondition implements Condition{
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
if("Windows 7".equals(environment.getProperty("os.name"))){
return true;
}
return false;
}
}
8.@Import 直接向容器中注入组件
1)直接注入bean,beanId 为 全路径名
@Configuration
@Import(C.class)
public class MyConfig {
beanId为: main.java.com.myAnnotation.entity.C
2)通过ImportSelector注入bean,beanId为全路径名
@Configuration
@Import({MyImportSelector.class})
public class MyConfig {
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.java.entity.C"};
}
}
3)通过ImportBeanDefinitionRegistrar注入bean,自定义beanId
@Configuration
@Import({MyImportBeanDefinitionRegistrar.class})
public class MyConfig {
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
BeanDefinition beanDefinition = new RootBeanDefinition(Java.class);
registry.registerBeanDefinition("java", beanDefinition); //自定义beanId为java
}
}
9.通过FactoryBean向容器注入bean
@Bean
public HtmlFactoryBean htmlFactoryBean(){
return new HtmlFactoryBean();
}
public class HtmlFactoryBean implements FactoryBean<Html> {
@Override
public Html getObject() throws Exception {
return new Html();
}
@Override
public Class<?> getObjectType() {
return Html.class;
}
@Override
public boolean isSingleton() {
return true; //默认是单例
}
}
applicationContext.getBean("htmlFactoryBean"),返回的是Html的实例;如果需要返回HtmlFactoryBean的实例,可以使用applicatioinContext.getBean("&htmlFactoryBean");
10.bean生命周期之initMethod,destroyMethod
@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
public C c(){
调用顺序: 构造函数->initMethod->destroyMethod
11.bean生命周期之InitializingBean,DisposableBean
public class Html implements InitializingBean, DisposableBean{
public Html(){
System.out.println("html constructor start...");
}
@Override
public void destroy() throws Exception {
System.out.println("html destroy start....");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("html afterPropertiesSet start...");
}
}
调用顺序 构造函数->afterPropertiesSet->destroy
12.bean生命周期之@PostConstruct,@PreDestroy
public class Html implements {
public Html(){
System.out.println("html constructor start...");
}
@PostConstruct
public void postConstruct(){
System.out.println("postConstruct start....");
}
@PreDestroy
public void preDestroy(){
System.out.println("preDestroy start....");
}
}
调用顺序: 构造函数->postConstruct->preDestroy
13.bean生命周期之BeanPostProcessor,针对所有的bean
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws
BeansException {
System.out.println("postProcessBeforeInitialization start ...");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws
BeansException {
System.out.println("postProcessAfterInitialization start ...");
return bean;
}
}
调用顺序: 构造函数->postProcessBeforeInitialization->postProcessAfterInitialization
BeanPostProcessor底层原理:
通过代码追踪: AbstractAutowireCapableBeanFactory 类有个方法initializeBean,部分代码截图如下:
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName); //
调用BeanPostProcessor的postProcessBeforeInitialization方法
}
try {
this.invokeInitMethods(beanName, wrappedBean, mbd); //调用@PostConstruct,InitializingBean等初始化方法
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null,
beanName, "Invocation of init method failed", var6);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);//调用BeanPostProcessor的postProcessAfterInitialization方法
}
14.bean生命周期调用顺序:
构造函数->BeanPostProcessor.postProcessBeforeInitialization->@PostConstruct->InitializingBean.afterPropertiesSet->initMethod->BeanPostProcessor.postProcessAfterInitialization->@PreDestroy->Disposable.destroy->destroyMethod
引入外部的properties文件,相当于xml配置中<context:property-placeholder location=""/>
@Configuration
@PropertySource({"classpath:/JS.properties"})
public class MyConfig {
给对象属性赋值,相当于xml配置文件中的<property name="" value=""/>
public class Js {
@Value("JS入门到精通") //直接赋值
private String name;
@Value("#{100*0.9}") //通过表达式赋值
private Integer price;
@Value("${JS.author}") //从配置文件中读取
private String author;
默认通过类型获取,如果同类型的有多个实例,则根据属性名称获取;
有required属性,默认true,容器中不存在引用的实例时报错
1)@Autowired放在属性上
public class Jsp {
@Autowired
private Js js;
2)@Autowired放在方法上
@Component
public class Python {
private Feature feature;
@Autowired
public void setFeature(Feature feature) { //从容器中获取feature实例 this.feature = feature;
}
@Bean
@Autowired
public Python python(Feature feature){ //从容器中获取feature实例 return new Python(feature); }
3)@Autowired放在构造函数上
@Component
public class Python {
private Feature feature;
@Autowired
public Python(Feature feature) {
this.feature = feature;
}
4)@Autowired放在参数上,如果类只有一个带参构造函数,可以不用@Autowired
@Component
public class Python {
private Feature feature;
public Python(@Autowired Feature feature) {
this.feature = feature;
}
@Bean
public Python python(Feature feature, C c){ //从容器中获取
return new Python(feature, c);
}
与@Autowired连用,引用特定的bean实例
public class Jsp {
@Qualifier(value="js0") //引用js0
@Autowired
private Js js;
与@Autowired连用,让spring进行自动装配的时候,默认使用首选的bean
@Primary
@Bean(name = "js")
public Js js(){
默认根据名称引入bean实例,可以通过name属性指定名称;
同@Autowired注解,不同的是没有required属性
20.ApplicationContextAware 获取 applicationContext实例
@Component
public class Company implements ApplicationContextAware{
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws
BeansException {
this.applicationContext = applicationContext;
}
底层原理: 存在一个ApplicationContextAwareProcessor后置处理器,会调用ApplicationContextAware实现类的setApplicationContext方法,其他xxxAware也有对应的后置处理器
针对不同的环境加载不同的配置,默认值为default
@Profile("test")
@Bean public Employee employee(){
Employee employee = new Employee();
employee.setName("zhangsan");
return employee;
}
@Profile("dev")
@Bean public Employee employee1(){
Employee employee = new Employee();
employee.setName("lisi");
return employee;
}
激活Profile
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.getEnvironment().setActiveProfiles("test"); //在环境启动前 配置profile属性
applicationContext. register(MyConfig.class);
applicationContext.refresh();
//得用无参构造函数, new AnnotationConfigApplicationContext(MyConfig.class); 会直接执行
//applicationContext.register(MyConfig.class);
//applicationContext.refresh();