Spring筆記(1) – 組件註冊
-
@Bean:類注入容器
- xml方式:
<bean id="person" class="com.hrh.bean.Person"> <property name="name" value="張三"></property> <property name="age" value="20"></property> </bean> public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Person person = (Person) context.getBean("person"); System.out.println(person); }
- @Bean+@Configuration方式:
@Configuration//配置類==配置文件 public class BeanConfig { @Bean public Person person(){ return new Person("張三",20); } } AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class); Person person = (Person)context.getBean("person");
- xml方式:
-
@ComponentScan:掃描類注入容器
- xml方式:
<!-- component-scan包掃描,只要標註了@Controller、@Service、@Repository、@Component的類會注入容器中 use-default-filters=false禁用默認過濾規則,使用自定義過濾規則 --> <context:component-scan base-package="com.hrh" use-default-filters="false"/>
- @ComponentScan方式:JDK1.8的ComponentScan是Repeatable的,即可以在類上定義多個@ComponentScan
@Configuration//配置類==配置文件 /** * value:指定要掃描的包 * includeFilters:指定掃描時只需要包含哪些組件,需要使用useDefaultFilters = false使規則生效 * excludeFilters:指定掃描時按照什麼規則排除哪些組件 */ @ComponentScan(value = "com.hrh",includeFilters = { @Filter(type = FilterType.ANNOTATION, classes = {Controller.class}) },useDefaultFilters = false) public class BeanConfig { @Bean public Person person(){ return new Person("張三",20); } } //====結果==== org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory beanConfig userController person
- @ComponentScans:如果不是JDK1.8,可以使用該註解定義多個@ComponentScan
@ComponentScans({ @ComponentScan(value = "com.hrh",includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}) },useDefaultFilters = false) }) public class BeanConfig { @Bean public Person person(){ return new Person("張三",20); } }
- @Filter:過濾規則
@Configuration//配置類==配置文件 /** * FilterType.ANNOTATION:根據註解掃描指定的類 * FilterType.ASSIGNABLE_TYPE:按照給定的類型,如果是介面類型,其實現類和子類注入容器;如果是類,本類和子類注入容器 * FilterType.ASPECTJ:使用ASPECTJ表達式 * FilterType.REGEX:使用正則表達式 * FilterType.CUSTOM:使用自定義規則,自定義實現TypeFilter介面,重寫match方法 */ @ComponentScan(value = "com.hrh", includeFilters = { // @ComponentScan.Filter(type = FilterType.ANNOTATION, // classes = {IUserService.class}), // @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, // classes = {IUserService.class}), @ComponentScan.Filter(type = FilterType.CUSTOM,classes ={MyTypeFilter.class} ) }, useDefaultFilters = false) public class BeanConfig { @Bean public Person person() { return new Person("張三", 20); } } public class MyTypeFilter implements TypeFilter { /** * * @param metadataReader 讀取到的當前正在掃描的類的資訊 * @param metadataReaderFactory 可以獲取到其他任何類的資訊 * @return ture則將類加入容器 * @throws IOException */ public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { //獲取當前類註解的資訊 AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); //獲取當前類資源(類路徑) Resource resource = metadataReader.getResource(); //獲取當前正在掃描的類的類資訊 ClassMetadata classMetadata = metadataReader.getClassMetadata(); String className = classMetadata.getClassName(); System.out.println("className:"+className); if(className.contains("Controller")){ return true; } return false; } } //====結果==== className:com.hrh.bean.Person className:com.hrh.config.MyTypeFilter className:com.hrh.controller.UserController className:com.hrh.dao.UserDao className:com.hrh.service.IUserService className:com.hrh.service.SubUserService className:com.hrh.service.UserService org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory beanConfig userController person
- xml方式:
-
@Scope:作用域
@Configuration @ComponentScan(value = "com.hrh") public class BeanConfig { /** * ConfigurableBeanFactory#SCOPE_PROTOTYPE:prototype * ConfigurableBeanFactory#SCOPE_SINGLETON:singleton * org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST:request * org.springframework.web.context.WebApplicationContext#SCOPE_SESSION:session * prototype:多實例,只有在獲取的時候才會注入容器,每次獲取都會進行創建對象注入不同的實例,每次獲取的對象都不同 * singleton:單實例(默認值),ioc容器啟動會調用該方法創建對象注入容器,每次獲取直接中容器中拿 * request:同一次請求創建一個實例 * session:同一個session創建一個實例 */ @Scope(value = "prototype") @Bean public Person person() { System.out.println("注入容器。。。。。"); return new Person("張三", 20); }
- @Lazy:懶載入,項目啟動時不創建對象注入容器,只在第一次調用時才創建對象並初始化
@Lazy @Bean public Person person() { System.out.println("注入容器。。。。。"); return new Person("張三", 20); }
- @Lazy:懶載入,項目啟動時不創建對象注入容器,只在第一次調用時才創建對象並初始化
-
@Conditional:按照條件注入容器,實現Condition的matches()
@Configuration @ComponentScan(value = "com.hrh") public class BeanConfig { @Conditional(WindowsConfig.class) @Bean(value = "Bill") public Person person1() { System.out.println("創建Windows。。。。。"); return new Person("Bill", 20); } @Conditional(LinuxConfig.class) @Bean(value = "Linux") public Person person2() { System.out.println("創建Linux。。。。。"); return new Person("Linux", 20); } } public class WindowsConfig implements Condition { /** * * @param context 判斷條件能使用的上下文 * @param metadata 注釋資訊 * @return */ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { //獲取ioc使用的beanFactory ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); //獲取類載入器 ClassLoader classLoader = beanFactory.getBeanClassLoader(); Environment environment = context.getEnvironment(); String property = environment.getProperty("os.name"); if("Windows 10".equals(property)){ return true;//當前系統環境是windows 10,將條件下的bean注入容器 } return false; } } public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { //獲取ioc使用的beanFactory ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); //獲取類載入器 ClassLoader classLoader = beanFactory.getBeanClassLoader(); Environment environment = context.getEnvironment(); String property = environment.getProperty("os.name"); if("Linux".equals(property)){ return true; } return false; }
-
@Import:快速導入組件進容器
public class Color { } @Configuration @ComponentScan(value = "com.hrh") @Import(Color.class) //@Import({Color.class,Person.class})導入多個 public class BeanConfig {} public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class); String[] beanDefinitionNames = context.getBeanDefinitionNames(); for(String beanName:beanDefinitionNames){ System.out.println(beanName); } }
-
ImportSelector:實現該介面,重寫selectImports()
public class MyImportSelector implements ImportSelector { /** * * @param importingClassMetadata 當前標註@Import的類的全部註解資訊,比如該類還標註了@Configuration也會被獲取到 * @return 返回的組件全類名加入到容器中 */ public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[]{"com.hrh.bean.Color","com.hrh.bean.Person"}; } } @Configuration @ComponentScan(value = "com.hrh") @Import({MyImportSelector.class}) public class BeanConfig {}
-
ImportBeanDefinitionRegistrar:實現ImportBeanDefinitionRegistrar,重寫registerBeanDefinitions()
@Configuration @Import({Color.class,MyImportBeanDefinitionRegistrar.class}) public class BeanConfig {} public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /** * * @param importingClassMetadata 當前類的註解資訊 * @param registry BeanDefinition註冊類,把所有需要添加到容器中的bean,調用BeanDefinitionRegistryregisterBeanDefinition註冊進來 */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean color = registry.containsBeanDefinition("com.hrh.bean.Color"); //容器中有Color類才將Person類進行注入 if(color) { RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Person.class); registry.registerBeanDefinition("person",rootBeanDefinition); } } }
-
-
FactoryBean
public class MyFactoryBean implements FactoryBean<Color> { //返回一個對象,並且該對象會注入容器 @Override public Color getObject() throws Exception { return new Color(); } @Override public Class<?> getObjectType() { return Color.class; } @Override public boolean isSingleton() { return true; } } @Configuration public class BeanConfig { /** * 1.默認獲取的是MyFactoryBean調用getObject創建的對象 * 2.要獲取MyFactoryBean本身,需要給id前加&,比如&myBeanFactory */ @Bean public MyFactoryBean myBeanFactory(){ return new MyFactoryBean(); } } AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class); Object bean1=context.getBean("myBeanFactory"); System.out.println(bean1.getClass()); Object bean2=context.getBean("&myBeanFactory"); System.out.println(bean2.getClass());