/**
* 构造方法注入 Bean
*/
private final UserService userService;
public BeanInjectionServiceImpl(UserService userService) {
logger.info("=====> 构造方法注入 Bean!");
this.userService = userService;
}
Set
函数的依赖注入
<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="student" class="com.li.entity.Student">
<property name="name" value="张三"/>
<property name="id" value="20"/>
bean>
beans>
@Test
public void test1() {
ClassPathResource resource = new ClassPathResource("StudentBean.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(resource);
Student student = factory.getBean(Student.class);
logger.info("当前 Stundet :{}", student);
}
<bean id="student" class="com.li.entity.Student">
<property name="name" value="张三"/>
<property name="id" value="20"/>
<property name="list">
<list>
<value>数学value>
<value>英语value>
list>
property>
bean>
@Test
public void test2() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("StundetBeanOne.xml");
Student bean = applicationContext.getBean(Student.class);
logger.info("当前 Student :{}", bean);
}
在Spring
中,BeanFactory
是 IoC
容器的核心接口。
ApplicationContext
是BeanFactory
的子接口,也被称为Spring
上下文。Application Context
是 spring
中较高级的容器。
两者详细比较见:https://blog.csdn.net/qq_37248504/article/details/113704298
SpringIOC
:控制反转,将对象的创建,装配,管理等一系列操作交给Spring
容器(BeanFactory、ApplicationContext
)进行处理。开发者只需要从容器中拿到对象使用。Bean
的配置、定义文件配置BeanFactory
。refresh()
方法完成。容器初始化
prepareRefresh()
:容器刷新前的准备、设置上下文状态、获取属性等。
prepareBeanFactory(beanFactory)
:配置标准的beanFactory
,设置ClassLoader
,设置SpEL
表达式解析器,添加忽略注入的接口,添加bean
,添加bean
后置处理器等。
postProcessBeanFactory(beanFactory)
:所有的beanDefinition
已经加载,但是还没有实例化。允许在子类中对beanFactory
进行扩展处理。比如添加ware
相关接口自动装配设置,添加后置处理器等,是子类扩展prepareBeanFactory(beanFactory)
的方法。在应用上下文的内部bean factory
初始化之后修改bean factory
。
registerBeanPostProcessors(beanFactory)
:实例化和注册beanFactory
中扩展了BeanPostProcessor
的bean
。将 BeanPostProcessor
注册到 BeanFactory
中,并没有执行
initMessageSource()
:初始化国际化工具类MessageSource
initApplicationEventMulticaster()
:初始化事件广播器
onRefresh()
:模板方法,在容器刷新的时候可以自定义逻辑,不同的Spring容器做不同的事情。
registerListeners()
:注册监听器
finishBeanFactoryInitialization(beanFactory)
:实例化所有剩余的(非懒加载)单例
比如invokeBeanFactoryPostProcessors
方法中根据各种注解解析出来的类,在这个时候都会被初始化。实例化的过程各种BeanPostProcessor
开始起作用。
finishRefresh()
:refresh
做完之后需要做的其他事情。清除上下文资源缓存(如扫描中的ASM元数据) 初始化上下文的生命周期处理器,并刷新(找出Spring容器中实现了Lifecycle
接口的bean
并执行start()
方法)。发布ContextRefreshedEvent
事件告知对应的ApplicationListener
进行响应的操作。
容器初始化详见:https://blog.csdn.net/qq_37248504/article/details/113704298
Bean
:对于BeanFactory
容器,请求的Bean
没有初始化的时候,容器会调用createBean()
进行实例化。对于ApplicationContext
容器,当容器启动结束后,通过获取BeanDefinition
对象中的信息,实例化所有的bean
。bean
设置相关属性和依赖。Bean
:在返回Bean
之前做一些处理BeanNameAware
的setBeanName()
BeanFactoryAware
的setBeanFactory()
ApplicationContextAware
的setAllicationContext()
BeanPostProcessor
的前置处理方法InitializingBean
的afterPropertiesSet()
init-method
方法BeanPostProcessor
的后置处理方法spring
在创建BeanA
的时候会先去一级缓存获取,如果一级缓存没有则再从二级缓存中获取,如果二级缓存也没有,则再从三级缓存中获取,如果还获取不到,则实例化一个A
,然后放入三级缓存,然后填充属性,此刻发现依赖B
,于是创建B
,同样的经过上述步骤,由于每级缓存都获取不到,于是实例化B
,然后填充属性,发现依赖A
,然后依次去每级缓存中获取,由于三级缓存中已经有一个A
,于是B
可以顺利注入依赖,并被正确的初始化,然后递归返回,于是A
也可以被正确的初始化了。@Autowired
通过Bean
的类型注入Bean
,当容器中含有多个相同类型的Bean
时候,可以使用@Qualifier
指定Bean
的名称@Resource
通过Bean
的Name
进行注入,是Java
中的注解。事务管理器
PlatformTransactionmanger
:commit()
提交事务、rollback()
回滚事务、getTransaction()
获取事务的状态。事务定义信息
TransactionDefinition
:用来定义事务相关的属性(事务隔离级别、事务传播方式、超时时间、是否只读)。事务具体运行状态
TransactionStatus
:判断事务是否完成、当前事务是否是一个新事务等。@Transaction
,这种方式对代码没有侵入性。需要手动写事务提交等相关的代码
事务传播机制等内容见博客:https://blog.csdn.net/qq_37248504/article/details/107008217
Aop
可以将一些非业务代码、公共的代码和业务代码进行解耦操作,定义切点、定义切面,在切面中进行公共方法的处理。使用切面操作,可以减少系统的重复代码,降低模块之间的耦合度,有利于后期的维护开发。Aop元素
切点(PoinCut
):从哪些类哪个方法切入,可以配合注解使用。
通知(Advice
):在方法执行前、或者执行后进行需要的操作。
切面(Aspect
):整个切面中进行切点和通知的操作,编写代码。
织入(Weaving
):由Spring
完成,创建代理对象。
Aop
注解方式记录接口日志见例子见博客:https://blog.csdn.net/qq_37248504/article/details/102926592
singleton
:单例,默认作用域。prototype
:原型,每次创建一个新对象。request
:请求,每次Http请求创建一个新对象,适用于WebApplicationContext
环境下。session
:会话,同一个会话共享一个实例,不同会话使用不用的实例。global-session
:全局会话,所有会话共享一个实例。Bean
,所有的线程共享一个单例实例Bean
。大多数时候Bean
都是无状态的Bean
,所以是安全的。Prototype
)类型的Bean
,每次请求都会创建一个新的Bean
,这样就可以保证线程安全了。Scope
范围测试:当使用原型模式的时候,普通变量可以做到线程安全,但是静态变量是有问题的。所以使用还是得要按照实际开发结合。@RestController
@RequestMapping("/spring/testone")
@Scope(value = "prototype")
public class SpringTestTwoController {
private static final Logger logger = LoggerFactory.getLogger(BeanTestController.class);
private int a = 0;
private static int b = 0;
@RequestMapping("/test1")
public void test1() {
logger.info("普通变量 a:{} 静态变量 b:{}", ++a, ++b);
}
@RequestMapping("/test2")
public void test2() {
logger.info("普通变量 a:{} 静态变量 b:{}", ++a, ++b);
}
}
Spring
要在需要的时候每次生产一个,新的 bean
实例,bean
的 scope
属性被指定为 prototype
。另一方面,一个 bean
每次使用的时候必须返回同一个实例,这个 bean
的 scope
属性 必须设为singleton
。bean
的作用域的种类可见上面的知识点。Swagger
是接口API文档,可以更加清晰的看到接口的参数、类型等。Swagger
的使用请见:https://blog.csdn.net/qq_37248504/article/details/106773321Swagger
常用注解请见博客:https://blog.csdn.net/qq_37248504/article/details/106797105Controller
默认是单例的,正因为单例所以不是线程安全的。@Scope(“prototype”)
定义变量等。ThreadLocal
。spring-core
:基础API
模块,如资源管理,泛型处理。
spring-beans
:Spring Bean
相关,依赖查找,依赖注入。
spring-aop
:动态代理,aop
字节码提升。
spring-context
:事件驱动,注解驱动,模块驱动。
spring-expression
: spring
表达式语音模块。
BeanFactory
:Spring
底层的基础容器。常用的BeanFactory是XmlBeanFactory,根据xml定义的内容创建bean。Application
:ApplicationContext
在BeanFactory
的基础上构建,是相对比较高 级的容器实现,除了拥有BeanFactory
的所有支持,ApplicationContext
还提供了其他高级,比如事件发布、国际化信息支持等。@SpringBootApplication
@SpringBootApplication
@EnableCaching
@EnableScheduling
@MapperScan("com.li.springbootproject.mapper")
public class TestProjectApplication {
public static void main(String[] args) {
SpringApplication.run(TestProjectApplication.class);
}
}
@SpringBootApplication
注解:开启自动配置功能@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}
AutoConfigurationImportSelector
选择器给Spring
容器中导入一下组件。@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
java jar
包类路径下的META-INF/spring.factories
文件META-INF/spring.factories
里面配置的所有 EnableAutoConfiguration
的值加入到 Spring
容器中。RequestMapping
不仅能相应Post
请求,还能相应Get
请求。GetMapping
只能相应get
请求。
其它常用注解,详细见博客:https://blog.csdn.net/qq_37248504/article/details/108859121
跨域:浏览器不能执行其他网站的脚本。
解决办法:使用nginx
做代理,代理到同一个域下;再后端配置拦截器做请求拦截校验处理。
详细见博客:https://blog.csdn.net/qq_37248504/article/details/107347488
SpringBoot
打的jar
包不能被其他类引用,不能被其他项目所依赖。SpringBoot
打包成的可执行 jar
解压后,在 \BOOT-INF\classes
目录下才是我们的代码。SpringBoot
主要通过实例化SpringApplication
来启动,启动的过程中主要进行:配置属性、获取监听器、发布应用开始启动事件、初始化输入参数、配置环境、输出banner
、创建上下文、预处理上下文、刷新容器、发布应用已启动事件。public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
// 启动监听器
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();
Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//第二步,根据SpringApplicationRunListeners以及参数来准备环境
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
// 在控制台打印 banner
Banner printedBanner = this.printBanner(environment);
// 创建 Spring 容器
context = this.createApplicationContext();
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
// Spring 容器 前置处理
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 刷新容器
this.refreshContext(context);
// Spring 容器后置处理
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
// 发出结束执行的事件
listeners.started(context);
// 执行 Runners
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
try {
listeners.running(context);
// 返回容器
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
@Order
标识类的顺序,数字越小越靠前。
实现ApplicationRunner
接口
@Component
@Order(1)
public class TestProjectApplicationRunner implements ApplicationRunner {
private static final Logger logger = LoggerFactory.getLogger(TestProjectApplicationRunner.class);
@Autowired
private Environment environment;
@Override
public void run(ApplicationArguments args) throws Exception {
logger.info("----------> TestProjectApplicationRunner 初始化!");
logger.info("----------> 当前服务端口为:{}",environment.getProperty("server.port"));
}
}
CommandLineRunner
接口@Component
@Order(2)
public class TestProjectCommandLineRunner implements CommandLineRunner {
private static final Logger logger = LoggerFactory.getLogger(TestProjectCommandLineRunner.class);
private Environment environment;
public TestProjectCommandLineRunner(Environment environment) {
this.environment = environment;
}
@Override
public void run(String... args) throws Exception {
logger.info("----------> TestProjectCommandLineRunner 初始化!");
logger.info("----------> 当前服务端口为:{}",environment.getProperty("server.port"));
}
}
ApplicationEvent
,可以用来传递需要处理的数据。ApplicationEventPublisherAware
通过实现这个接口,来触发事件。SpringBoot
事件同步异步处理详见博客:https://blog.csdn.net/qq_37248504/article/details/115269995Spring Boot Admin
用来管理和监控Spring Boot
应用程序。应用程序向我们的Spring Boot Admin Client
注册(通过HTTP
)或使用SpringCloud
(例如 Eureka
,Consul
)发现UI
是Spring Boot Actuator
端点上的Vue.js
应用程序 。Quartz
定时任务框架:https://blog.csdn.net/qq_37248504/article/details/106874496Scheduled
定时任务器:https://blog.csdn.net/qq_37248504/article/details/106874449ApplicationContextAware
接口,重写setApplicationContext()
在这个方法中可以拿到上下文ApplicationContext
。@Component
public class SpringContextUtils implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// 在这里可以拿到当前容器的上下文
}
}
@Autowired
private ApplicationContext applicationContext;
classpath
路径下创建一个banner.txt
即可。