表示当前类是一个配置类
@Configuration
public class MainConfig {
}
用来注入bean对象,和在xml中的
@Configuration
public class MainConfig {
//在Bean标签中有一个value值 表示给book取一个别名
@Bean
public Book book(){
return new Book();
}
}
需要扫描的包。在@ComponentScan有许多的参数
@Value:指定扫描的包
@excludeFilters:指定扫描的时候按照规则排除哪些组件
@includeFilters:指定扫描的时候只扫描配置的组件
@Filter:过滤的规则,默认是Annotation类型,主要一下几种类型
ANNOTATION, //按照注解
ASSIGNABLE_TYPE,//按照给定类型
ASPECTJ,//按照aspectj,基本不怎么用
REGEX,//按照正则
CUSTOM;//按照自定义
//扫描类
@Configuration
@ComponentScan(value = "com.jack",includeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM,classes =
{MyFilterTye.class})},
useDefaultFilters = false)
public class ComponentScanConfig {
}
//自定义配置类
public class MyFilterTye implements TypeFilter {
/**
*
* @param metadataReader 当前类信息
* @param metadataReaderFactory 正在扫描类的信息
* @return
* @throws IOException
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获取当前类的注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(类路径)
Resource resource = metadataReader.getResource();
//获取正在扫描类名
String className = classMetadata.getClassName();
System.out.println("------>"+className);
if (className.contains("ok")){
return true;
}
return false;
}
}
//测试类
public class TestMain {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext annotationConfigApplicationContext =
new AnnotationConfigApplicationContext(MainConfig.class);
Book bean = annotationConfigApplicationContext.getBean(Book.class);
String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
for (String name : beanDefinitionNames){
System.out.println(name);
}
}
}
bean实例的作用域范围,默认在spring容器中是单例的
prototype:多实例,ioc容器在启动并不会取调用方法创建对象放在容器中,每次获取的时候才会调用方法取创建
singleton:单实例(默认值),ioc容器启动的会自动创建bean实例放到ioc容器中,以后每次获取bean实例直接从ioc容器中拿
//这个两个用的比较少,主要在浏览器请求的时候进行创建
request:同一次请求创建一个实例
session:同一个session创建一个实例
懒加载,在实例注入bean实例的时候,在启动容器的时候不进行创建实例,在第一调用的时候创建bean实例
@Configuration
public class MainConfig {
@Lazy
@Bean
public Book book(){
return new Book();
}
}
按照一定的条件进行判断,满足条件给容器注册bean
如果作用在方法上,对一个bean注册的条件过滤
如果在类上,表示对整个类进行条件过滤
//根据条件进行注册bean
@Configuration
@Import({ComponentScanConfig.class})
public class MainConfig {
@Bean
public Book book(){
return new Book();
}
@Conditional(LinuxCindition.class)
@Bean("book1")
public Book book1(){
return new Book("平凡的世界",92.1);
}
@Conditional(WindowsCondition.class)
@Bean("book2")
public Book book2(){
return new Book("简爱",90.0);
}
}
/**
* @description 判断是否是Linux系统
* @author: zq
* @create: 2021-07-21 22:51
**/
public class LinuxCindition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//1.获取ioc的BeanFactory
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
//获取类加载器
ClassLoader classLoader = conditionContext.getClassLoader();
//获取当前环境信息
Environment environment = conditionContext.getEnvironment();
//获取bean定义的注册类
BeanDefinitionRegistry registry = conditionContext.getRegistry();
//判断操作系统
String property = environment.getProperty("os.name");
if (property.contains("Linux")){
return true;
}
return false;
}
}
//判断是否是windows系统
public class WindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//判断操作系统
//获取当前环境信息
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("os.name");
if (property.contains("Windows")){
return true;
}
return false;
}
}
//在创建对象的时候会根据条件来进行创建
给容器导入一个组件,id就是组件的类名,比如导入三方包中的组件
@Import({ComponentScanConfig.class})
返回值就是要导入到组件中的全类名
//实现ImportSelector接口
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{"com.jack.bo.Blue","com.jack.bo.Yellow"};
}
}
在@import注解中添加MyImportSelector类
@Import({ComponentScanConfig.class,MyImportSelector.class})
通过手动注册bean到容器中,使用方法和ImportSelector类似,实ImportBeanDefinitionRegistrar接口,然后通过Import注解注入到bean中
作用:通过实现FactoryBean,可以对bean实例进行定制实例化的bean,简单的来说就是可以根据自己的需求对bean实例进行包装,注入到容器中。
bean的初始化和销毁方法
在@Bean注解上initMethod和destroyMethod方法
初始化
? 单例:是在对象创建完成,复制完成之后调用初始化方法,
销毁:
? 单例:是在容器关闭的时候调用销毁方法
? 多例:容器不会管理这个bean,容器不会调用销毁方法,需要进行手动销毁
@Bean(initMethod = "init",destroyMethod = "destory")
public Blue blue(){
return new Blue();
}
? Bean通过实现InitializingBean和DisposableBean接口,都是初始化赋值和销毁
@Component
public class InitBean implements InitializingBean, DisposableBean {
public InitBean() {
System.out.println("创建一个InitBean");
}
@Override
public void destroy() throws Exception {
System.out.println("InitBean destroy=======");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitBean afterPropertiesSet=======");
}
}
@PostConstruct:在bean实例创建赋值完成之后,进行初始化
@PreDestory:在容器移除bean的时候进行,进行调用
@Component
public class PostConstructorBean {
public PostConstructorBean() {
System.out.println("---》创建PostConstructorBean");
}
@PostConstruct
public void initPostConstructorBean(){
System.out.println("---》初始化initPostConstructorBean");
}
@PreDestroy
public void preDestroy(){
System.out.println("---> 销毁前调用preDestroy");
}
}
Bean的后置处理器,在bean的初始化前后进行一些操作
postProcessBeforeInitialization:初始化前调用
postProcessAfterInitialization:初始化之后调用
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化前==MyBeanPostProcessor");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化厚==MyBeanPostProcessor");
return bean;
}
}
//源码解读
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//前置处理方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//后置处理方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
BeanPostProcessor注解有很强大的功能,在Spring底层支持:
bean的赋值,注入其他组件,@Autowired注解,@Async异步注解等等都是通过BeanPostProcessor来的
为属性进行赋值
基本参数
使用SpEL:#{}
配置文件中取值:${}
@Value("平凡的世界")
private String name;
@Value("#{20.2-10.1}")
private Double price;
@Value("${person.author}")
private String author;
加载properties配置文件,可以通过classpath或者file的方式加载
/**
* Indicate the resource location(s) of the properties file to be loaded.
* For example, {@code "classpath:/com/myco/app.properties"} or
* {@code "file:/path/to/file"}.
* <p>Resource location wildcards (e.g. **/*.properties) are not permitted;
* each location must evaluate to exactly one {@code .properties} resource.
* <p>${...} placeholders will be resolved against any/all property sources already
* registered with the {@code Environment}. See {@linkplain PropertySource above}
* for examples.
* <p>Each location will be added to the enclosing {@code Environment} as its own
* property source, and in the order declared.
*/
String[] value();
@PropertySource(value = {"classpath:/person.properties"})
自动注入依赖实例的值
@Qualifier
指定需要封装的主键id,来注入属性
require
配和@Autowired使用,表示属性为非必须的
@Primary
在spring进行自动装配的时候,默认使用首先的bean;也可以使用@Qualifier指定继续使用哪个
@Service
public class BooKService {
@Qualifier("book1")
@Autowired(required = false)
private BooKDao booKDao2;
}
@Autowired可以使用在方法之上,但是获取值是获取ioc容器中的值
@Autowired可以使用在构造器上,获取值也是从ioc容器中获取 ,如果只有有参构造器,可以省略掉@Autowired注解
@Autowired可以使用在参数位置,获取值也是从ioc容器中获取
@Resource和@Inject是属于java中的注解规范,spring也是支持
@Resource:
? 可以实现@Autowired一样的自动装配功能,默认按照组件的名称进行装配
? 但是没有@Primary优先的和require的功能
@Inject:
? 需要引入javax的包,和Autowired功能是一样的
需要实现XXXAware接口,比如ApplicationContexAware接口等等
public class Yellow implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境都不会被注册。
/*
在dev环境中会加载实例bean
*/
@Configuration
public class MainConfigOfProfile {
@Profile("dev")
@Bean
public Book Book(){
return new Book("111",90.1);
}
}
原文:https://www.cnblogs.com/JackQiang/p/15059115.html