learning com.maidou 1.0-SNAPSHOT 4.0.0 spring-escape spring-escape http://www.example.com UTF-8 1.7 1.7 org.springframework.boot spring-boot-dependencies 2.6.4 pom import junit junit 4.13.1 test org.springframework.boot spring-boot-starter-web 2.6.4 org.projectlombok lombok 1.18.24 org.springframework.boot spring-boot-starter-test 2.6.4 mysql mysql-connector-java 8.0.21 runtime org.apache.commons commons-lang3 3.8.1 maven-clean-plugin 3.1.0 maven-resources-plugin 3.0.2 maven-compiler-plugin 3.8.0 maven-surefire-plugin 2.22.1 maven-jar-plugin 3.0.2 maven-install-plugin 2.5.2 maven-deploy-plugin 2.8.2 maven-site-plugin 3.7.1 maven-project-info-reports-plugin 3.0.0
package com.maidou.spring.escape.service;import org.springframework.stereotype.Service;@Service
public class ORderService {public void getOrder() {System.out.println("this is order");}
}
package com.maidou.spring.escape.service;import com.maidou.spring.escape.utils.ApplicationUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import static org.junit.Assert.*;@SpringBootTest
@RunWith(SpringRunner.class)
public class ORderServiceTest {@Testpublic void getOrder() {ORderService oRderService = (ORderService)ApplicationUtils.getBean("oRderService");oRderService.getOrder();}
}
package com.maidou.spring.escape.utils;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;/*** 应用上下文工具类
* */
@Slf4j
@Component
public class ApplicationUtils implements ApplicationContextAware {private static ApplicationContext applicationContext = null;@Overridepublic void setApplicationContext(ApplicationContext applicationContext)throws BeansException {if (ApplicationUtils.applicationContext == null) {ApplicationUtils.applicationContext = applicationContext;}}public static ApplicationContext getApplicationContext() {return ApplicationUtils.applicationContext;}/*** 通过 name 获取 Bean
* */public static Object getBean(String name) {return getApplicationContext().getBean(name);}/*** 通过 class 获取 Bean
* */public static T getBean(Class clazz) {return getApplicationContext().getBean(clazz);}/*** 通过 name + class 获取 Bean
* */public static T getBean(String name, Class clazz) {return getApplicationContext().getBean(name, clazz);}
}
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'oRderService' availableat org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:874)at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1344)at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:309)at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
AnnotationBeanNameGenerator -> generateBeanName -> Introspector.decapitalize(shortClassName)
public static String decapitalize(String name) {if (name == null || name.length() == 0) {return name;}// 第一个字母和第二个字母都是大写的话本名输出if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&Character.isUpperCase(name.charAt(0))){return name;}char chars[] = name.toCharArray();chars[0] = Character.toLowerCase(chars[0]);return new String(chars);}
属性对象注入了,但是,当前类没有被标记为new
当前类标记为spring bean,且属性对象也注入了,但是,确实用了new去过去了对象
解决方式 : 使用bean 的整个过程中,都应该被Spring容器所管理
创建外部类
import org.springframework.stereotype.Service;@Service
public class Outer {public void test() {System.out.println("outer test");}
}
单元测试
@Testpublic void testOuter() {assert ApplicationUtils.getApplicationContext().containsBean("outer");((Outer)ApplicationUtils.getBean("outer")).test();}
错误
java.lang.AssertionErrorat com.maidou.spring.escape.service.ORderServiceTest.testOuter(ORderServiceTest.java:26)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) 解决方式 启动类增加扫描包信息
@ComponentScan(value = {"com.maidou.spring.escape","com.maidou.spring.outer"})
@ComponentScan 参数说明
Spring的核心是管理对象,且并不只是帮我们创建对象,他负责了对象整个生命的管理,创建、装配、销毁
他是IOC容器
应用上下文可以认为是Spring容器的一种实现,也就是用于操作容器类对象
把需要管理的对象放入容器中,取得容器中的Bean
1. 最简单的容器2. 提供基本的DI功能
1. 解析配置文件2. 注册管理Bean
定义在org.springframwork.context包下,两步实现
package com.maidou.spring.escape.application_context;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;/*** 保存应用上下文
* */
@Slf4j
public class ApplicationContextStore {private static ApplicationContext applicationContext = null;public static void setApplicationContext(ApplicationContext applicationContext) {log.info("coming in applicationContextStore");if (ApplicationContextStore.applicationContext == null) {ApplicationContextStore.applicationContext = applicationContext;}}public static ApplicationContext getApplicationContext() {return ApplicationContextStore.applicationContext;}
}
获取应用上下文
package com.maidou.spring.escape.application_context;import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;/*** @Author maicheng* @Description : 第一种方式获取应用上下文* @Date 13:13 2022/10/22**/
@Slf4j
public class UserInitializer implements ApplicationContextInitializer {@Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {assert ApplicationContextStore.getApplicationContext() == null;ApplicationContextStore.setApplicationContext(applicationContext);assert ApplicationContextStore.getApplicationContext() != null;log.info("get UserInitializer");}
}
注册到启动类上
public static void main(String[] args) {
// SpringApplication.run(App.class, args);SpringApplication application = new SpringApplication(App.class);application.addInitializers(new UserInitializer());application.run(args);}
观察者的典型应用(内置事件)
ApplicationContexntEvent
coding
package com.maidou.spring.escape.application_context;import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;/*** @Author maicheng* @Description* @Date 13:28 2022/10/22**/
@Slf4j
@Component
public class UserListener implements ApplicationListener {@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {assert ApplicationContextStore.getApplicationContext() == null;ApplicationContextStore.setApplicationContext(event.getApplicationContext());assert ApplicationContextStore.getApplicationContext() != null;log.info("get UserListener");}
}
注释掉 注册的UserInitializer
coding
package com.maidou.spring.escape.application_context;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;/*** @Author maicheng* @Description :第三种应用上下文的方式* @Date 13:44 2022/10/22**/
@Component
@Slf4j
public class UserAware implements ApplicationContextAware {@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {assert ApplicationContextStore.getApplicationContext() == null;ApplicationContextStore.setApplicationContext(applicationContext);assert ApplicationContextStore.getApplicationContext() != null;log.info("get UserAware");}
}
启动类原始启动 参考
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SUY7FZiU-1666420944363)(C:\Users\maido\AppData\Roaming\Typora\typora-user-images\image-20221022135911320.png)]](/uploadfile/202401/7d9e700e1f19638.png)
package com.maidou.spring.escape.singleton_;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;@Slf4j
@Service
public class DefaultSingleton {private List list = null;@PostConstructpublic void init() {log.info("Coming in DefaultSingleton");this.list = new ArrayList<>(100);}public void add(String result) {list.add(result);}public int getSize() {return list.size();}public List getList() {return this.list;}
}
测试
package com.maidou.spring.escape.singleton_;import com.maidou.spring.escape.utils.ApplicationUtils;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import static org.junit.Assert.*;@SpringBootTest
@RunWith(SpringRunner.class)
@Slf4j
public class DefaultSingletonTest {@Testpublic void init() {DefaultSingleton bean = ApplicationUtils.getBean(DefaultSingleton.class);DefaultSingleton bean1 = ApplicationUtils.getBean(DefaultSingleton.class);assert bean.hashCode() == bean1.hashCode();bean.add("11111");bean.add("222222");log.info("bean info : {}", bean.getList());bean1.add("33333");log.info("bean info : {}", bean.getList());}
}
映射成多个对象 改变scope 模式
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
线程不安全
属于Spring 框架,默认使用类型(byType)进行注入
结合@Autowired一起使用,自动注入策略由byType变成byName
JAVAEE 自带的注解,默认按byName自动注入
存在多个类型的相同类型的Bean,则 @Primary用于定义首选项
上一篇:@Import注解详解
下一篇:全排列笔记