Spring再次学习(1)
时隔一年多,在掌握了Spring、SpringBoot、SpringCloud之后
我再次回头,重新学习Spring框架
回顾以前的内容:
组件注册:
最早使用,是XML的方式:
导入依赖:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.12.RELEASE</version> </dependency>
一个实体类:
package org.dreamtech.bean; public class Person { private String name; private Integer age; @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } public Person() { } public Person(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
View Code
XML:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="person" class="org.dreamtech.bean.Person"> <property name="name" value="张三"/> <property name="age" value="18"/> </bean> </beans>
测试类:
package org.dreamtech; import org.dreamtech.bean.Person; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainTest { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); Person bean = (Person) applicationContext.getBean("person"); System.out.println(bean); } }
打印:
Person{name='张三', age=18}
完成
后来,开始使用注解方式,不需要XML配置
写一个配置类:
package org.dreamtech.config; import org.dreamtech.bean.Person; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 配置类 */ @Configuration public class MainConfig { @Bean public Person person(){ return new Person("李四",20); } }
测试类:
package org.dreamtech; import org.dreamtech.bean.Person; import org.dreamtech.config.MainConfig; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MainTest { public static void main(String[] args) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class); Person bean = applicationContext.getBean(Person.class); System.out.println(bean); } }
打印:
Person{name='李四', age=20}
扫描Bean:扫描@Controller@Service等
在XML中的方式是:
<context:component-scan base-package="org.dreamtech.bean"/>
注解方式是:
@ComponentScan(value = "org.dreamtech")
根据我们开发常用的架构,新建类:
package org.dreamtech.controller; import org.springframework.stereotype.Controller; @Controller public class BookController { }
package org.dreamtech.service; import org.springframework.stereotype.Service; @Service public class BookService { }
package org.dreamtech.dao; import org.springframework.stereotype.Repository; @Repository public class BookDao { }
然后查看Spring容器中所有的Bean:
package org.dreamtech.test; import org.dreamtech.config.MainConfig; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class IOCTest { @Test public void test() { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class); String[] definitionNames = applicationContext.getBeanDefinitionNames(); for (String name : definitionNames) { System.out.println(name); } } }
打印如下:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookDao
bookService
person
在扫描的时候,可以进行过滤,指定哪些需要扫描,哪些不需要:
比如我想排除Controller注解类的扫描:
@ComponentScan(value = "org.dreamtech", excludeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}) })
测试成功
比如我只想扫描Controller注解类:
@ComponentScan(value = "org.dreamtech", includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}) })
测试失败
原因:需要禁用掉默认扫描规则
@ComponentScan(value = "org.dreamtech", includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})}, useDefaultFilters = false)
以上是按照注解进行过滤的,实际上还有很多其他的方式,但是不经常使用
比如:指定类、AspectJ表达式、正则表达式、自定义
排除指定类(包括子类等)
@ComponentScan(value = "org.dreamtech", excludeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}), @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {BookService.class})} )
值得关注的是自定义规则:需要实现一个TypeFilter接口
我自定义只能扫描到包含字符串”er”的类
package org.dreamtech.config; import org.dreamtech.bean.Person; import org.dreamtech.service.BookService; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.core.type.filter.TypeFilter; import org.springframework.stereotype.Controller; /** * 配置类 */ @Configuration @ComponentScan(value = "org.dreamtech", includeFilters = { @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})}, useDefaultFilters = false ) public class MainConfig { @Bean public Person person() { return new Person("李四", 20); } }
package org.dreamtech.config; import org.springframework.core.io.Resource; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.ClassMetadata; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.TypeFilter; import java.io.IOException; public class MyTypeFilter implements TypeFilter { /** * 实现 * * @param metadataReader 当前正在扫描的类 * @param metadataReaderFactory 可以获取到其他任何类的信息 * @return 是否匹配 * @throws IOException 异常 */ 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("er")) { return true; } return false; } }
测试后打印:
[-------------org.dreamtech.bean.Person-------------] [-------------org.dreamtech.config.MyTypeFilter-------------] [-------------org.dreamtech.controller.BookController-------------] [-------------org.dreamtech.dao.BookDao-------------] [-------------org.dreamtech.MainTest-------------] [-------------org.dreamtech.service.BookService-------------] [-------------org.dreamtech.test.IOCTest-------------] org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory mainConfig person myTypeFilter bookController bookService
相关文章