Spring 注解编程IOC

Bean 注册

注册Bean的常用注解有@Component、@Service、@Controller、@Repository,通过扫描包的方式对这些注解进行解析注册Bean。

注解ApplicationContext:AnnotationConfigApplicationContext

常用注解

@Configuration

声明Bean Difinition的配置文件,相当于一个xml文件

@Bean

<code>@Configuration
public class CustomConfig {
@Bean
public Person person() {
return new Person();
}
}
/<code>

相当于xml bean内容

<code><beans>
<bean>
/<beans>
/<code>

bean的名称默认为方法名称,也可以通过@Bean(value="person")或者@Bean("person")进行指定

@ComponentScan

指定扫描路径

<code>@Configuration
@ComponentScan("top.felixfly.spring.annotation")
public class ScanConfiguration {
}
/<code>

相当于xml component-scan

<code><beans>
<component-scan>
/<beans>
/<code>

@ComponentScans

多个扫描路径,值为ComponentScan的数组,1.8以后可以用多个@ComponentScan代替此注解

@Scope

指定Bean的作用域,默认为singleton

singleton org.springframework.beans.factory.config.ConfigurableBeanFactory#SCOPE_SINGLETONprototype org.springframework.beans.factory.config.ConfigurableBeanFactory#SCOPE_PROTOTYPErequest org.springframework.web.context.WebApplicationContext#SCOPE_REQUESTsession org.springframework.web.context.WebApplicationContext#SCOPE_SESSION

<code>@Configuration
public class CustomConfig {
@Bean
@Scope("singleton")
public Person person() {
return new Person();
}
}
/<code>

相当于xml中bean中scope属性

<code><beans>
<bean>
/<beans>
/<code>

@Lazy

懒加载,针对singleton Bean进行懒加载,默认情况下单实例Bean直接加载

<code>@Configuration
public class CustomConfig {
@Bean
@Lazy
public Person person() {
return new Person();
}
}
/<code>

相当于xml中bean的lazy-init属性

<code><beans>
<bean>
/<beans>
/<code>

@DependsOn

依赖关系注解

<code>@Configuration
public class CustomConfig {



@Bean
@DependsOn("person")
public Manager manager(){
return new Manager();
}

@Bean
public Person person(){
return new Person();
}
}
/<code>

相当于xml中bean的depends-on属性

<code><beans>
<bean>
/<beans>
/<code>

@Order

Bean的排序,或者说是优先级,两个接口org.springframework.core.Ordered以及org.springframework.core.PriorityOrdered,主要使用优先级的内容

org.springframework.beans.factory.config.BeanPostProcessororg.springframework.http.converter.HttpMessageConverter

@Conditional

条件装配Bean

实现org.springframework.context.annotation.Condition接口public class CustomCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // true 进行装配,false不进行装配
return false; } }Bean上配置@Conditional(Condition.class)@Configuration public class CustomConfig { @Conditional(CustomCondition.class) @Bean public Person person() { return new Person(); } }

当matches方法返回true的时候进行注册当前@Bean,否则不注册。该注解也可以放到配置类上,matches方法返回true的时候进行注册当前配置类,否侧不注册。

@Profile

环境注解,底层使用的是@Conditional

@Import

快捷注册Bean,默认名称为类的全路径

直接导入类@Configuration @Import(Person.class) public class
CustomConfig { }导入实现org.springframework.context.annotation.ImportSelector类public class CustomImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { return new String[]{Person.class.getName()}; } } @Configuration @Import(CustomImportSelector.class) public class CustomConfig { }导入实现org.springframework.context.annotation.ImportBeanDefinitionRegistrar类public class CustomImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) { // 自行注册BeanDefinition RootBeanDefinition beanDefinition =
new RootBeanDefinition(Person.class); registry.registerBeanDefinition("person",beanDefinition); } } @Configuration @Import(CustomImportBeanDefinitionRegistrar.class) public class CustomConfig { }

@ImportResource

导入资源xml文件

资源文件名称spring/application-spring.xml

<code><beans>
<bean>
<constructor-arg>
<constructor-arg>
/<bean>
/<beans>
/<code>

<code>@Configuration
@ImportResource("classpath:/spring/application-spring.xml")
public class CustomConfig {
}
/<code>

常见问题

@Configuration、其他注解与@Bean结合使用有什么不同

答:@Configuration注解使用的其实也是一个Bean,但本身是BeanFatory,是经过CGLIB进行增强的Bean,其他注解(@Component、@Service、@Controller、@Repository)使用的就是一个简单的Bean

Bean 依赖注入

常用注解

@Autowired

Spring自带的自动注入,注解的属性required来支持是否必须要进行依赖注入。根据以下规则进行查找进行注入

根据类型查找,只查询一个直接返回根据名称查找

<code>@Service
public class PersonService {

@Autowired
private PersonMapper personMapper;
}
/<code>

可以结合以下注解进行使用

@Qualifier指定名称进行依赖注入@Service public class PersonService { @Autowired @Qualifier("personMapper") private PersonMapper personMapper; }@Primary指定优先进行依赖注入@Service public class PersonService { @Autowired private PersonMapper personMapper; } @Configuration @ComponentScan({"top.felixfly.spring.annotation.mapper","top.felixfly.spring.annotation.service"})
public class CustomConfig { // 优先注入 @Bean("personMapper2") @Primary public PersonMapper personMapper(){ return new PersonMapper(); } }

只有一个有参构造器时,@Autowired可以省略,可以自动进行注入

@Resource

Java规范(JSR250)的注解,默认按照属性的名称进行依赖查找匹配,也可以用属性name进行强制指定,但不支持与@Primary注解结合使用和required是否必须要进行依赖注入

<code>@Service
public class PersonService {

@Resource
private PersonMapper personMapper;
}

@Service
public class PersonService {
\t// 强制指定Bean
@Resource(name="personMapper2")
private PersonMapper personMapper;
}
/<code>

@Inject

Java规范的注解(JSR330),功能与@Autowired一样,但不支持required是否必须要进行依赖注入。需要引入javax.inject

<code><dependency>
<groupid>javax.inject/<groupid>
<artifactid>javax.inject/<artifactid>
<version>1/<version>
/<dependency>
/<code>

<code>@Service
public class PersonService {

@Inject
private PersonMapper personMapper;
}
/<code>

注入方式

构造器注入

<code>@Configuration
public class AppConfig {

@Bean
public BeanOne beanOne() {
// 构造器注入
return new BeanOne(beanTwo());
}

@Bean
public BeanOne beanThree(BeanTwo beanTwo) {
// 构造器注入
return new BeanOne(beanTwo);
}

@Bean
public BeanTwo beanTwo() {
return new BeanTwo();
}
}
/<code>

Setter方法注入

<code>public class BeanTwo {

@Autowired
public void setBeanOne(BeanOne beanOne) {
this.beanOne = beanOne;
}
}


/<code>

Aware接口

自定义组件注入Spring底层的组件,比如ApplicationContext,这些Aware接口一般通过Processor进行处理。ApplicationContextAwareProcessor处理EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware

ApplicationContextAwareApplicationContextApplicationEventPublisherAwareApplicationContext事件发布器BeanClassLoaderAware类加载器BeanFactoryAwareBean 工厂BeanNameAwareBean 名称BootstrapContextAwareBootstrapContextMessageSourceAware国际化管理NotificationPublisherAwareSpring JMX通知发布器ResourceLoaderAware资源加载器EmbeddedValueResolverAware@Value解析器EnvironmentAware环境变量

常见问题

循环依赖的问题

答:循环依赖的产生,BeanA依赖BeanB,BeanB依赖BeanC,而BeanC又依赖于BeanA,这时候就会产生循环依赖的问题,单例Bean中通过构造器注入会产生循环依赖的问题,会产生BeanCurrentlyInCreationException,通过Setter方法注入不会产生异常,可以解决循环依赖问题。原型@Bean通过Setter方法注入依然会产生BeanCurrentlyInCreationException,没办法解决循环依赖问题。

Bean 生命周期

Bean的生命周期包含实例化–>初始化–>销毁,单实例Bean实例化在容器创建的时候进行实例化以及初始化,销毁在容器关闭的时候进行调用;多实例Bean在获取Bean的时候进行实例化以及初始化,销毁需要自行进行调用。

初始化和销毁常用方法

@Bean指定initMethod和destroyMethod@Configuration
public class CustomConfig { @Bean(initMethod = "init",destroyMethod = "destroy") public Person person(){ return new Person(); } } 相当于xml中配置init-method和destroy-method属性<beans> <bean> /<beans>实现InitializingBean和DisposableBeanpublic class Person implements InitializingBean, DisposableBean { public Person() { } @Override public void afterPropertiesSet() throws Exception { } @Override public void destroy
() throws Exception { } }使用@PostConstruct和@PreDestroy注解使用InitDestroyAnnotationBeanPostProcessor进行解析处理,父类CommonAnnotationBeanPostProcessorpublic class Person { public Person() { } @PostConstruct public void postConstruct(){ } @PreDestroy public void preDestroy(){ } }

BeanPostProcessor

postProcessBeforeInitialization 初始化之前执行方法postProcessAfterInitialization 初始化之后执行方法

<code>public class CustomBeanPostProcessor implements BeanPostProcessor {

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}


@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
/<code>

<code>@Configuration
@Import(CustomBeanPostProcessor.class)


public class CustomConfig {

@Bean
public Person person(){
return new Person();
}
}
/<code>

执行方法若是返回null值,后续的BeanPostProcessor不会进行执行,源代码执行如下:

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

<code>@Override
\tpublic Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
\t\t\tthrows BeansException {

\t\tObject result = existingBean;
\t\tfor (BeanPostProcessor processor : getBeanPostProcessors()) {
\t\t\tObject current = processor.postProcessBeforeInitialization(result, beanName);
\t\t\tif (current == null) {
\t\t\t\treturn result;
\t\t\t}
\t\t\tresult = current;
\t\t}
\t\treturn result;
\t}

\t@Override
\tpublic Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
\t\t\tthrows BeansException {

\t\tObject result = existingBean;
\t\tfor (BeanPostProcessor processor : getBeanPostProcessors()) {
\t\t\tObject current = processor.postProcessAfterInitialization(result, beanName);
\t\t\tif (current == null) {
\t\t\t\treturn result;
\t\t\t}
\t\t\tresult = current;
\t\t}
\t\treturn result;
\t}

/<code>

常见问题

生命周期执行方法顺序

答:初始化方法执行顺序

@PostConstruct实现InitializingBean接口的方法@Bean指定initMethod

销毁方法执行顺序

@PreDestroy实现DisposableBean接口的方法@Bean指定destroyMethod

Multiple lifecycle mechanisms configured for the same bean, with different initialization methods, are called as follows:

Methods annotated with @PostConstructafterPropertiesSet() as defined by the InitializingBean callback interfaceA custom configured init() method

Destroy methods are called in the same order:

Methods annotated with @PreDestroydestroy() as defined by the DisposableBean callback interfaceA custom configured destroy() method

资源属性赋值

常用注解

@Value

属性进行赋值,可以有如下三种写法

直接赋值public class Person { @Value("张三") private String name; }SpEL表达式 #{}public class Person { @Value("#{20-2}") private String age; }${} 文件属性赋值(通常在环境变量Enviroment中),要配合@PropertySource使用
public class Person { @Value("${person.age}") private String age; }

@PropertySource

引入配置文件,配置文件下根路径下person.properties

<code>@PropertySource("classpath:/person.properties")
public class CustomConfig {

}
/<code>

相当于xml中的context:property-placeholder

<code><property-placeholder>
/<code>

@PropertySources

多个配置文件引入,值为PropertySource的数组,1.8以后可以用多个@PropertySource代替此注解

常见问题

配置文件属性乱码

答:注解@PropertySource通过属性encoding进行配置文件编码,该配置在4.3版本引入;xml配置文件中通过属性file-encoding配置文件编码

粉丝福利:

为粉丝讲解福利资源:特讲解教程教你如何学习 ,源码、分布式、微服务、性能优化、多线程并发,从0到1,

带你领略底层精髓。

详情点击链接:https://shimo.im/docs/VqQR6tPrpR3C3tjq/