spring
1.spring框架原理介绍、spring框架环境搭建
1.Spring框架是轻量级的JavaEE框架
2.Spring可以解决企业应用开发的复杂性
3.Spring有两个核心部分:IOC和Aop
- IOC:控制反转,把创建对象的过程交给Spring进行管理
- Aop:面向切面编程,不修改源代码进行功能增强
4.Spring特点
- 非侵入的
- 方便解耦,简化开发
- Aop变成支持
- 方便程序测试
- 方便和其他框架进行整合
- 方便进行事物操作
- 降低API开发难度
spring环境的搭建
- 使用创建一个maven的web项目
- 在pom.xml中导入spring项目所需的包。
spring项目所需的四个jar包是spring-core,spring-beans,spring-context,spring-expression。
但是由于最终是要整合SSM开发web项目,这里就使用spring-web和spring-webmvc这两个包就行了。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.13</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
- 在resources目录下添加spring配置文件springcontext.xml。该配置文件的作用主要是定义bean、开启注解扫描、aop的配置等等。
- 在web.xml中初始化spring容器。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springcontext.xml</param-value>
</context-param>
<!--设置监听器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
- 配置tomcat服务器spring项目就搭建完成了。
2.学习创建Bean的方式及实现原理、Bean种类、Bean生命周期
Bean的创建
1、创建一个BeanFactory。
2、完成对xml配置文件和注解的扫描,将bean封装为BeanDefinition。
3、将BeanDefinition加入到BeanFactory。
4、添加并启动BeanFactory后置处理器。
5、增强BeanDefinition功能,补充bean。例如ConfigurationClassPostProcessor就是一个BeanFactory后置处理器,可以将@Configuration注解下的bean添加到BeanFactory,也可以解析@ComponentScan注解,扫描对应的包。
6、BeanDefinition通过反射创建bean对象。
7、启动bean后置处理器。BeanPostProcess可以增强bean的功能,如在实例化前后增强bean功能,Spring中内置的AutowiredAnnotationBeanPostProcessor可以处理@Autowire和@Value注解,提供依赖注入的支持。
8、实例化bean对象
9、依赖注入。
8、初始化。
下面是对bean的创建过程的演示
public class BeanLifeCycle {
public static void main(String[] args) {
//1、创建一个BeanFactory。
GenericApplicationContext beanFactory = new GenericApplicationContext();
//2、完成对xml配置文件和注解的扫描,将bean封装为BeanDefinition。
//会得到一个bean为com.fiber.config.StudentConfig@564fabc8,但是不能得到里面定义bean
beanFactory.registerBean("studentConfig",StudentConfig.class);
//3、添加并启动BeanFactory后置处理器。这时可以处理@ComponentScan和@Bean了
//得到扫描的com.fiber.bean.AddressConfig$$EnhancerBySpringCGLIB$$1abb854f@791f145a
//以及定义的student1,address1,address2这个bean。
beanFactory.registerBean("configurationScan", ConfigurationClassPostProcessor.class);
//4、注册bean后处理器,处理@Autowired,@Value注解
beanFactory.getDefaultListableBeanFactory().setAutowireCandidateResolver(
new ContextAnnotationAutowireCandidateResolver()
);
beanFactory.registerBean(AutowiredAnnotationBeanPostProcessor.class);
//注册bean后处理器,处理@Resources,PostProcess,PreDestroy注解
beanFactory.registerBean(CommonAnnotationBeanPostProcessor.class);
beanFactory.refresh();
beanFactory.getBeansOfType(Object.class).values().forEach(System.out::println);
beanFactory.close();
}
}
Bean的种类
- 普通bean:bean的class类型和创建的bean对象类型一样。
<bean id="address3" class="com.fiber.pojo.Address"/>
- FactoryBean:class类型和bean对象类型不一样。创建一个工厂类,实现FactoryBean接口
public class AddressFactory implements FactoryBean<Address> {
@Override
public Address getObject() throws Exception {
Address address = new Address();
address.setUniversity("FactoryBean");
address.setCity("FactoryBean");
address.setProvince("FactoryBean");
return address;
}
@Override
public Class<?> getObjectType() {
return Address.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
配置文件中配置bean
<bean id="address5" class="com.fiber.config.AddressFactory"/>
Bean的生命周期
Bean的生命周期分为4个阶段:
1、构造:调用类的无参构造方法。
2、依赖注入:为bean注值,会扫描@Resource,@Autowired,@Value等注解。
3、初始化:对象创建完成,并赋值好,调用初始化方法。
4、摧毁:单例模式下关闭容器时摧毁,多例模式下容器不会管理这个bean。
@Slf4j
public class LifeCycle {
@Resource
private AddressConfig address;
LifeCycle(){
log.info("构造方法");
}
@Autowired
public String getJAVAHOME(@Value("${JAVA_HOME}") String s){
log.info("执行依赖注入");
return s;
}
@PostConstruct
public void postConstructor(){
log.info("初始化");
}
@PreDestroy
public void postDestroy(){
log.info("摧毁");
}
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("cycle",LifeCycle.class);
context.registerBean("address",AddressConfig.class);
//一些bean的后处理器
//用来解析@Autowired和@Value
context.getDefaultListableBeanFactory().setAutowireCandidateResolver(
new ContextAnnotationAutowireCandidateResolver()
);
context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
//用来解析@Resource,@PostConstructor,@PreDestroy
context.registerBean(CommonAnnotationBeanPostProcessor.class);
context.refresh();
context.close();
}
}
2022-07-25 15:26:06.187 |-INFO
[main] com.fiber.config.LifeCycle [25] -| 构造方法
2022-07-25 15:26:06.256 |-INFO
[main] com.fiber.config.LifeCycle [29] -| 执行依赖注入
2022-07-25 15:26:06.256 |-INFO
[main] com.fiber.config.LifeCycle [34] -| 初始化
2022-07-25 15:26:06.256 |-INFO
[main] com.fiber.config.LifeCycle [39] -| 摧毁
3.学习Bean的作用域、Bean的注值方式
bean的作用域
- singleton:单例,使用的对象是同一个
- prototype:多例,每次会创建一个新的对象
Bean的注值方式
- 通过构造器注入
<bean id="address" class="com.fiber.pojo.Address">
<constructor-arg index="0" value="湖北省"/>
<constructor-arg index="1" value="武汉市"/>
<constructor-arg index="2" value="武汉理工大学"/>
</bean>
<bean id="address1" class="com.fiber.pojo.Address">
<constructor-arg name="province" value="黑龙江省"/>
<constructor-arg name="city" value="哈尔滨市"/>
<constructor-arg name="university" value="哈尔滨工程大学"/>
</bean>
- 通过set注入
通过set构造时可以对java基本类型和引用类型进行初始化赋值。也可以使用其他的bean对象注入。
<bean id="student1" class="com.fiber.pojo.Student">
<property name="name" value="彭锦坤"/>
<property name="books">
<array>
<value>book1</value>
<value>book2</value>
<value>book3</value>
</array>
</property>
<property name="address" ref="address"/>
<property name="hobby">
<list>
<value>hobby1</value>
<value>hobby2</value>
<value>hobby3</value>
</list>
</property>
<property name="card">
<map>
<entry key="id_card" value="id_card_XXXXXXX"/>
<entry key="student_card" value="student_card_XXXXXX"/>
</map>
</property>
<property name="games">
<set>
<value>game1</value>
<value>game2</value>
<value>game3</value>
</set>
</property>
<property name="wife">
<null/>
</property>
<property name="info">
<props>
<prop key="gender">male</prop>
<prop key="age">20</prop>
</props>
</property>
</bean>
- 自动装配
byName:通过名称自动装配
Student类有一个Address属性,如果属性名为address1,会查找id=address1的bean。
<bean id="student" class="com.fiber.pojo.Student" autowire="byName"/>
byType:通过类型自动装配
会查找bean的class类型为Address 的bean,如果有多个bean类型均为Addess,会出错。
<bean id="student" class="com.fiber.pojo.Student" autowire="byName"/>
4.注解装配Bean
1、定义bean对象的注解
- @Component:通用的
- @Service:用于服务层
- @Controller:用于控制层
- @Repository:用于DAO层
2、开启注解支持,会补充bean的后处理器。
<context:annotation-config/>
3、扫描包里面的注解
<context:component-scan base-package="com.fiber"/>
4、依赖注入
- @Autowired
只按照byType注入(可结合@Qualifier一起使用,在无法按类型匹配时按照名字匹配bean)。 - @Resource
默认byName注入,如果byName无法找到就通过byType查找。