@Configuration:声明一个配置类
@Bean:向容器中注册bean,bean的类型为方法返回值类型,ID默认就是方法名。可以通过修改@Bean注解的value属性或者方法名来修改beanID
//配置类=配置文件
@Configuration
public class MainConfig {
//向容器中注册bean,类型为返回值类型,ID默认就是方法名
@Bean("person")
public Person person01(){
return new Person("zhangsan",23);
}
}
public class MainTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
Person person = applicationContext.getBean(Person.class);
System.out.println(person);
String[] beanNamesForType = applicationContext.getBeanNamesForType(Person.class);
for (int i = 0; i < beanNamesForType.length; i++) {
System.out.println(beanNamesForType[i]);
}
}
}
-
使用Spring提供的FactoryBean:默认获取到的是FactoryBean调用getObject返回的对象,想要获取FactoryBean本身,需要在bean id前加“&”
@Configuration @import({MyimportBeanDefinitionRegistrar.class}) public class MainConfig3 { @Bean public MyFactoryBean myFactoryBean() { return new MyFactoryBean(); } }public class MyFactoryBean implements FactoryBean
{ @Override public Product getObject() throws Exception { return new Product(); } @Override public Class> getObjectType() { return Product.class; } @Override public boolean isSingleton() { return true; } } @Test public void mainConfig3Test() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig3.class); Object bean = context.getBean("myFactoryBean"); System.out.println("bean的类型:"+bean.getClass()); }@Test public void mainConfig3Test() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig3.class); Object bean = context.getBean("&myFactoryBean"); System.out.println("bean的类型:"+bean.getClass()); }
@ComponentScan:指定包扫描的路径。可以把指定路径下标注了@Controller、@Repository、@Service、@Component注解的类加到容器中。可以通过includeFilters和excludeFilters来指定添加和剔除哪些组件。
//配置类=配置文件
@Configuration
@ComponentScan(value = "com.hjw", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {Dao.class})
})
//FilterType.ANNOTATION:按注解过滤
//FilterType.ASSIGNABLE_TYPE:按类型过滤
//FilterType.CUSTOM:自定义规则
public class MainConfig {
//向容器中注册bean,类型为返回值类型,ID默认就是方法名
@Bean("person")
public Person person01(){
return new Person("zhangsan",23);
}
}
public class IOCTest {
@Test
public void test1(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
String[] names = context.getBeanDefinitionNames();
for (int i = 0; i < names.length; i++) {
System.out.println(names[i]);
}
}
}
@org.springframework.stereotype.Controller
public class Controller {
}
@org.springframework.stereotype.Service
public class Service {
}
@Repository
public class Dao {
}
自定义FilterType
public enum FilterType {
ANNOTATION,
ASSIGNABLE_TYPE,
ASPECTJ,
REGEX,
CUSTOM
}
通过实现org.springframework.core.type.filter.TypeFilter来自定义过滤器
public class MyFilter implements TypeFilter {
@Override
public boolean match(metadataReader metadataReader, metadataReaderFactory metadataReaderFactory) throws IOException {
// 当前类的注解信息
Annotationmetadata annotationmetadata = metadataReader.getAnnotationmetadata();
// 当前类信息
Classmetadata classmetadata = metadataReader.getClassmetadata();
String className = classmetadata.getClassName();
System.out.println("当前扫描到的类名:"+className);
return false;
}
}
@Scope
-
singleton:单例的(默认值),容器启动时会创建对象放在容器中,以后每次获取都是从容器中拿。
@Configuration public class MainConfig2 { @Bean public Person person(){ System.out.println("创建person"); return new Person("李四", 18); } }@Test public void scopeTest() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig2.class); Object p1 = context.getBean("person"); Object p2 = context.getBean("person"); System.out.println(p1 == p2); }
-
prototype:多实例的,容器启动时不会创建对象,每次获取的时候才创建对象
@Configuration public class MainConfig2 { @Scope("prototype") @Bean public Person person(){ System.out.println("创建person"); return new Person("李四", 18); } } -
request:同一个请求创建一个实例
-
session:同一个session创建一个实例
单实例bean,默认在容器启动的时候创建对象。懒加载:容器启动时不创建对象。第一次获取bean时才创建对象,并初始化。
@Lazy
@Bean
public Person person(){
System.out.println("创建person");
return new Person("李四", 18);
}
@Test
public void scopeTest() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig2.class);
System.out.println("容器创建完成");
// Object p1 = context.getBean("person");
// Object p2 = context.getBean("person");
// System.out.println(p1 == p2);
}
打开注解时
@Conditional按照一定条件进行判断,满足条件则给容器中注册bean
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@documented
public @interface Conditional {
Class extends Condition>[] value();
}
可以作用在类和方法上,值Condition类
public class MyConditional implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypemetadata metadata) {
BeanDefinitionRegistry registry = context.getRegistry();
return registry.containsBeanDefinition("person");
}
}
@Configuration
public class MainConfig2 {
// @Scope("prototype")
// @Lazy
// @Bean
// public Person person(){
// System.out.println("创建person");
// return new Person("李四", 18);
// }
@Conditional({MyConditional.class})
@Bean
public Person james() {
System.out.println("创建James");
return new Person("james", 23);
}
@Bean
public Person kobe() {
System.out.println("创建Kobe");
return new Person("Kobe", 24);
}
}
@Test
public void scopeTest() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig2.class);
System.out.println("容器创建完成");
}
@import
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
public @interface import {
Class>[] value();
}
-
@import(要导入容器的组件),id默认是全类名
@Configuration @import({Person.class}) public class MainConfig2 { // @Scope("prototype") // @Lazy // @Bean // public Person person(){ // System.out.println("创建person"); // return new Person("李四", 18); // } // @Conditional({MyConditional.class}) @Bean public Person james() { System.out.println("创建James"); return new Person("james", 23); } @Bean public Person kobe() { System.out.println("创建Kobe"); return new Person("Kobe", 24); } }@Test public void scopeTest() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig2.class); System.out.println("容器创建完成"); String[] definitionNames = context.getBeanDefinitionNames(); for (int i = 0; i < definitionNames.length; i++) { System.out.println(definitionNames[i]); } } -
importSelector:返回要导入组件的全类名
public interface importSelector { String[] selectimports(Annotationmetadata importingClassmetadata); }@Configuration @import({MyimportSelect.class}) public class MainConfig3 { }public class MyimportSelect implements importSelector { @Override public String[] selectimports(Annotationmetadata importingClassmetadata) { return new String[]{"com.hjw.bean.person","com.hjw.bean.animal"}; } }@Test public void mainConfig3Test() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig3.class); String[] definitionNames = context.getBeanDefinitionNames(); for (int i = 0; i < definitionNames.length; i++) { System.out.println(definitionNames[i]); } }
-
importBeanDefinitionRegistrar:手动注册
public interface importBeanDefinitionRegistrar { void registerBeanDefinitions(Annotationmetadata importingClassmetadata, BeanDefinitionRegistry registry); }@Configuration @import({MyimportBeanDefinitionRegistrar.class}) public class MainConfig3 { }public class MyimportBeanDefinitionRegistrar implements importBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(Annotationmetadata importingClassmetadata, BeanDefinitionRegistry registry) { RootBeanDefinition beanDefinition = new RootBeanDefinition(Card.class); registry.registerBeanDefinition("myCard", beanDefinition); } }@Test public void mainConfig3Test() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig3.class); String[] definitionNames = context.getBeanDefinitionNames(); for (int i = 0; i < definitionNames.length; i++) { System.out.println(definitionNames[i]); } }
给容器中注册组件:
- 包扫描+组件标注注解(@Controller/@Service/@Respository/@Component)
- @Bean,导入第三方包里的组件
- @import
public class Plane {
public Plane(){
System.out.println("plane constructor");
}
public void initMethod() {
System.out.println("plane initMethod");
}
public void destroyMethod() {
System.out.println("plane destroyMethod");
}
}
@Configuration
public class MainConfig4 {
@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
public Plane plane(){
return new Plane();
}
}
@Test
public void mainConfig4Test() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig4.class);
System.out.println("容器创建完成");
context.close();
}
InitializingBean接口&DisposableBean接口欧
public interface InitializingBean {
// 在所有属性设置完成后会调用
void afterPropertiesSet() throws Exception;
}
public interface DisposableBean {
// 在BeanFactory销毁时调用
void destroy() throws Exception;
}
public class Plane implements InitializingBean, DisposableBean {
public Plane(){
System.out.println("plane constructor");
}
public void initMethod() {
System.out.println("plane initMethod");
}
public void destroyMethod() {
System.out.println("plane destroyMethod");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("plane afterPropertiesSet");
}
@Override
public void destroy() throws Exception {
System.out.println("plane destroy");
}
}
@PostConstruct&@PreDestroy
@documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
// 在bean初始化完成并且依赖注入完成执行方法
}
@documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PreDestroy {
// 在容器移除bean之前回调通知
}
public class Plane implements InitializingBean, DisposableBean {
public Plane(){
System.out.println("plane constructor");
}
public void initMethod() {
System.out.println("plane initMethod");
}
public void destroyMethod() {
System.out.println("plane destroyMethod");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("plane afterPropertiesSet");
}
@Override
public void destroy() throws Exception {
System.out.println("plane destroy");
}
@PostConstruct
public void post() {
System.out.println("plane PostConstruct");
}
@PreDestroy
public void preDestroy() {
System.out.println("plane PreDestroy");
}
}
BeanPostProcessor接口
// bean的后置处理器,在bean初始化前后进行一些操作
public interface BeanPostProcessor {
// 在已经创建的bean实例任何初始化方法调用前调用该方法
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
// 在已经创建的bean实例任何初始化方法调用后调用该方法
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
@Component
public class MyPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization beanName:" + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization beanName:" + beanName);
return bean;
}
}
@Configuration
@ComponentScan("com.hjw.bean")
public class MainConfig4 {
@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
public Plane plane(){
return new Plane();
}
}
-
原理
打个断点看下大致的方法调用栈
到mainConfig4Test,创建IOC容器
创建IOC容器
调用refresh方法,实例化所有剩下的单实例对象
实例化所有剩下的单例
创建bean>属性赋值>初始化
在初始化方法前后执行applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)和applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)
遍历所有的BeanPostProcessor,调用postProcessBeforeInitialization方法,如果返回null,不再执行后面的BeanPostProcessor
-
BeanPostProcessor在Spring底层的使用
BeanPostProcessor的实现类
-
ApplicationContextAwareProcessor注入IOC容器
在ApplicationContextAwareProcessor的postProcessBeforeInitialization方法中会调用invokeAwareInterfaces方法,在invokeAwareInterfaces方法中根据bean实现的接口注入相对应的资源
-
InitDestroyAnnotationBeanPostProcessor处理@PostConstruct和@PreDestroy注解的方法
找到生命周期注解标注的方法,调用对应的方法
-
- 可以使用基本数值
- 可以使用SpEL:#{}
- 可以使用${}:取配置文件中的值(运行环境变量的值 )
Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值。通过AutowiredAnnotationBeanPostProcessor实现自动装配。
@Autowired- 默认优先按类型去容器中找对应的组件
- 如果找到多个相同类型的组件,再将属性名作为组件的id在容器中查找
- 可以使用@Qualifier指定需要装配的组件id,而不是属性名作为组件id
- 可以使用@Primary让Spring在自动装配的时候,默认使用首选的bean
@Configuration
@ComponentScan({"com.hjw.service"})
public class AutowriredConfig {
@Bean("cardDao")
public CardDao cardDao() {
return new CardDao("cardDao");
}
@Primary
@Bean("cardDao1")
public CardDao cardDao1() {
return new CardDao("cardDao1");
}
}
@org.springframework.stereotype.Service
public class Service {
@Autowired
private CardDao cardDao;
@Override
public String toString() {
return "Service{" +
"cardDao=" + cardDao +
'}';
}
}
@Test
public void autowireTest() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AutowriredConfig.class);
Service service = context.getBean(Service.class);
System.out.println(service);
}
@Resource(JSR250)&@Inject(JSR330)【java规范的注解】
-
@Resource
可以和@Autowired一样实现自动装配,默认按组件名称装配。不支持@Primary,没有required属性
-
@Inject
需要导入javax.inject包
javax.inject javax.inject 1
自定义组件想要使用Spring容器底层的一些组件(eg:ApplicationContext,BeanFactory…),可以通过实现xxxAware接口注入Spring底层组件。在创建对象的时候,会调用接口中定义的相关方法完成组件注入。对应的xxxAware接口通过xxxAwareProcesssor实现。
@Profile根据环境注册bean。加了注解的bean,只有在这个环境被激活的时候才能注册到容器中。默认是default环境。
public class DataSource {
}
@Configuration
public class MainConfig5 {
@Profile("default")
@Bean("defaultDataSource")
public DataSource defaultDataSource() {
return new DataSource();
}
@Profile("test")
@Bean("testDataSource")
public DataSource testDataSource() {
return new DataSource();
}
@Profile("dev")
@Bean("devDataSource")
public DataSource devDataSource() {
return new DataSource();
}
}
@Test
public void profileTest() {
// AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig5.class);
// 创建容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 设置激活的环境
context.getEnvironment().setActiveProfiles("dev","test");
// 注册配置类
context.register(MainConfig5.class);
// 启动刷新容器
context.refresh();
String[] beanNamesForType = context.getBeanNamesForType(DataSource.class);
for (String beanName : beanNamesForType) {
System.out.println(beanName);
}
context.close();
}
中文文档
Spring中文文档



