持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第31天,点击查看活动详情
一、Spring
- spring编程模型
- spring的核心价值
- 设计思想
- 设计模式
- 用户基础
- 生态系统
- api抽象设计
- 编程模型
-
spring中的设计模式
-
Spring Framework有哪些核心模块
- spring-core:Spring基础API模块,如资源管理,泛型处理
- spring-beans:Spring Bean相关,如依赖查找,依赖注入
- spring-aop:Spring AOP处理,如动态代理,AOP字节码提升
- spring-context:事件驱动、注解驱动,模块驱动
- spring-expression:Spring表达式语言模块
二、IoC
- 什么是IoC?
是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。简单的说就是控制反转。其中最常见的实现方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。 2. IoC容器的职责
- 依赖处理
- 依赖查找
- 依赖注入
- 生命周期管理
- 容器
- 托管的资源
- 配置
- 容器
- 外部化配置
- 托管的资源
- IoC容器的实现
- 传统的Java Beans实现
获取bean的属性
BeanInfo beanInfo = Introspector.getBeanInfo(User.class, Object.class);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor:propertyDescriptors){
String propertyDescriptorName = propertyDescriptor.getName();
System.out.println(propertyDescriptorName);
}
- 依赖注入 VS 依赖查找
类型 | 依赖处理 | 实现便利性 | 代码侵入性 | API依赖性 | 可读性 |
---|---|---|---|---|---|
依赖查找 | 主动获取 | 相对繁琐 | 侵入业务逻辑 | 依赖容器API | 良好 |
依赖注入 | 被动提供 | 相对便利 | 低侵入性 | 不依赖容器API | 一般 |
- 构造器注入 VS Setter注入
Seeter注入的优点:
- 如果依赖关系较为复杂,那用构造函数注入的化会相对庞大
构造器注入的优点:
- 避免了繁琐的stter方法编写
- 符合了“在构造期即创建一个完整、合法的对象”的设计原则
- 由于没有setter方法的编写,组件创建后就处于“不变”的稳定状态,能够避免很多问题
- 通过构造器注入,意味着构造函数中决定了依赖关系的注入顺序,对于大量依赖外部服务的组件而言,依赖关系的获得顺序非常重要。
依赖查找:
public class Demo {
public static void main(String[] args) {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("dependency-lookup-context.xml");
lookupInLazyTime(beanFactory);
lookupCollection(beanFactory);
lookupByAnnotationType(beanFactory);
}
private static void lookupByAnnotationType(BeanFactory beanFactory) {
if(beanFactory instanceof ListableBeanFactory){
ListableBeanFactory listableBeanFactory=(ListableBeanFactory)beanFactory;
Map<String, Object> beans = listableBeanFactory.getBeansWithAnnotation(Super.class);
System.out.println(beans);
}
}
private static void lookupCollection(BeanFactory beanFactory) {
if(beanFactory instanceof ListableBeanFactory){
ListableBeanFactory listableBeanFactory=(ListableBeanFactory)beanFactory;
Map<String, Person> personMap = listableBeanFactory.getBeansOfType(Person.class);
System.out.println(personMap);
}
}
//实时查找
private static void lookupInRealTime(BeanFactory beanFactory) {
Person person = (Person) beanFactory.getBean("person");
System.out.println(person);
}
//延迟查找
private static void lookupInLazyTime(BeanFactory beanFactory) {
ObjectFactory<Person> objectFactory = (ObjectFactory<Person>)beanFactory.getBean("objectFactory");
Person person = objectFactory.getObject();
System.out.println(person);
}
}
依赖注入:
<bean id="userRepository" class="com.mmc.repository.UserRepository" autowire="byType"></bean>
- BeanFactory vs ApplicationContext
- BeanFactory是底层IoC容器
- ApplicationContext是具备应用特性的BeanFactory超集
- ApplicationContext除了是IOC容器外,还能提供:
- 面向切面(AOP)
- 配置元信息
- 资源管理
- 事件
- 国际化
- 注解
- Environment抽象
使用demo:
public class ApplicationDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext();
applicationContext.register(ApplicationDemo.class);
applicationContext.refresh();
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
@Bean
public Person person(){
Person person = new Person();
person.setAge(12);
person.setName("小慢");
return person;
}
}
- BeanFactory 与 FactoryBean?
- BeanFactory 是IoC底层容器
- FactoryBean 是创建Bean的一种方式,帮助实现复杂的初始化逻辑
- BeanFacory的运用
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory=new DefaultListableBeanFactory();
XmlBeanDefinitionReader beanDefinitionReader=new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.loadBeanDefinitions("dependency-lookup-context.xml");
System.out.println(Arrays.asList(beanFactory.getBeanDefinitionNames()));
Person person = (Person)beanFactory.getBean("person");
System.out.println(person);
}
三、Spring Bean
-
BeanDefintion元信息
-
Bean定义的方式
BeanDefinitionBuilder beanDefinitionBuilder=BeanDefinitionBuilder.genericBeanDefinition(Person.class);
beanDefinitionBuilder.addPropertyValue("name","小哥");
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
System.out.println(beanDefinition);
- 注册Spring Bean
- XML配置方式
- <bean name="" ...>
- Java注解配置方式
- @Bean
- @Component
- @Import
@Import(AnnotationRegisterBeanDemo.Config.class)
public class AnnotationRegisterBeanDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AnnotationRegisterBeanDemo.class);
applicationContext.refresh();
System.out.println(applicationContext.getBean(Config.class));
System.out.println(applicationContext.getBean(User.class));
applicationContext.close();
}
@Component
public static class Config{
@Bean
public User user(){
User user=new User();
user.setName("实施");
return user;
}
}
}
- Java Api配置方式
- BeanDefinitionRegistry#registerBeanDefinition
- BeanDefinitionReaderUtils#registerWithGeneratedName
- AnnotationConfigApplicationContext#register
public static void registerBeanDefinition(BeanDefinitionRegistry registry,String beanName,Class<?> beanClass){
BeanDefinitionBuilder beanDefinitionBuilder=BeanDefinitionBuilder.genericBeanDefinition(beanClass);
beanDefinitionBuilder.addPropertyValue("name","wanger");
if(StringUtils.hasText(beanName)){
registry.registerBeanDefinition(beanName,beanDefinitionBuilder.getBeanDefinition());
}else {
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinitionBuilder.getBeanDefinition(),registry);
}
}
public static void registerBeanDefinition(BeanDefinitionRegistry registry,Class<?> beanClass){
registerBeanDefinition(registry,null,beanClass);
}
- 实例化Bean
- 标准方式
- 通过构造器
- 通过静态工厂方法
- 通过Bean工厂
- 通过FactoryBean
- 特殊方式
- ServiceLoader
在MEAT-INF/services
目录下创建一个文件,以接口的全路径为文件名,内容为实现类的全路径
- ServiceLoader
在MEAT-INF/services
public class ServiceLoaderDemo {
public static void main(String[] args) {
ServiceLoader<UserFactory> serviceLoader=ServiceLoader.load(UserFactory.class, Thread.currentThread().getContextClassLoader());
Iterator<UserFactory> iterator = serviceLoader.iterator();
while (iterator.hasNext()){
UserFactory next = iterator.next();
System.out.println(next.createUser());
}
}
}
- SpringBean的初始化
- @PostConstruct
- Bean initMethod
- 实现InitializingBean接口
- AbstractBeanDefinition#setInitMethodName
- Spring的延迟加载
- XML配置:lazy-init="true"
- @Lazy注解
- SpringBean的销毁
- @PreDestroy
- 实现DisposableBean接口
- @Bean的destroyMethod