Spring学习

Spring学习

1.介绍

#优点:
1.Spring是一个开源的免费的容器框架
2.Spring是一个轻量级的、非入侵式的框架
3.Spring是一个IOC(DI)和AOP容器框架

#Springboot
1.一个快速开发的脚手架,快速开发单个微服务
2.约定大于配置
#Spring Cloud
1.SpringCloud基于SpringBoot实现,是一个微服务治理组件

#组成
1. Data Access/Integration(数据访问/集成)
数据访问/集成层包括 JDBC、ORM、OXM、JMS 和 Transactions 模块,具体介绍如下。
JDBC 模块:提供了一个 JDBC 的抽象层,大幅度减少了在开发过程中对数据库操作的编码。
ORM 模块:对流行的对象关系映射 API,包括 JPA、JDO、Hibernate 和 iBatis 提供了的集成层。
OXM 模块:提供了一个支持对象/XML 映射的抽象层实现,如 JAXB、Castor、XMLBeans、JiBX 和 XStream。
JMS 模块:指 Java 消息服务,包含的功能为生产和消费的信息。
Transactions 事务模块:支持编程和声明式事务管理实现特殊接口类,并为所有的 POJO。
2. Web 模块
Spring 的 Web 层包括 Web、Servlet、Struts 和 Portlet 组件,具体介绍如下。
Web 模块:提供了基本的 Web 开发集成特性,例如多文件上传功能、使用的 Servlet 监听器的 IoC 容器初始化以及 Web 应用上下文。
Servlet模块:包括 Spring 模型—视图—控制器(MVC)实现 Web 应用程序。
Struts 模块:包含支持类内的 Spring 应用程序,集成了经典的 Struts Web 层。
Portlet 模块:提供了在 Portlet 环境中使用 MV C实现,类似 Web-Servlet 模块的功能。
3. Core Container(核心容器)
Spring 的核心容器是其他模块建立的基础,由 Beans 模块、Core 核心模块、Context 上下文模块和 Expression Language 表达式语言模块组成,具体介绍如下。
Beans 模块:提供了 BeanFactory,是工厂模式的经典实现,Spring 将管理对象称为 Bean。
Core 核心模块:提供了 Spring 框架的基本组成部分,包括 IoC 和 DI 功能。
Context 上下文模块:建立在核心和 Beans 模块的基础之上,它是访问定义和配置任何对象的媒介。ApplicationContext 接口是上下文模块的焦点。
Expression Language 模块:是运行时查询和操作对象图的强大的表达式语言。
4. 其他模块
Spring的其他模块还有 AOP、Aspects、Instrumentation 以及 Test 模块,具体介绍如下。
AOP 模块:提供了面向切面编程实现,允许定义方法拦截器和切入点,将代码按照功能进行分离,以降低耦合性。
Aspects 模块:提供与 AspectJ 的集成,是一个功能强大且成熟的面向切面编程(AOP)框架。
Instrumentation 模块:提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用。
Test 模块:支持 Spring 组件,使用 JUnit 或 TestNG 框架的测试。

在这里插入图片描述

2.核心

#IOC 控制反转
原逻辑:程序主动创建对象,控制在程序员代码里
控制反转:使用set注入,程序不在主动创建对象,而是被动接收对象。大大降低耦合性
控制反转是通过DI(依赖注入)实现的,有三种注入方式:构造方法注入、set注入(最重要)、c命名空间和p命名空间注入(需要在xml文件中头添加相应约束)
##XML配置方式<bean>标签
<bean id="person" class="com.lmy.entity.Person">
      <property name="id" value="1"/>
      <property name="name" value="lmy"/>
      #<constructor-arg name>有参构造配置
</bean>
###xml配置方式获取Spring上下文对象,也可以把context理解为一个容器。
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
#getBean会加载bean到容器中,
#即new一个对象到Spring中(如有其他bean,没有get也会同时加载,可以通过无参构造测试)
Person person = (Person) context.getBean("person");
System.out.println(person);
##IOC创建对象的方式
1.通过无参构造方法。(默认方式)
2.通过有参构造(没有无参构造)<bean>中使用<constructor-arg>配置
##Bean的作用域
1.Singleton 单例 2.prototype原型模式(多例) 3.request 4.session 5.application

##**********Bean的自动装配******************
1.含义:自动装配是Spring满足bean依赖的一种方式,Spring会在上下文中自动寻找并被bean装配属性
2.三种方式: xml中装配、java配置文件基于注解装配、隐式的自动装配(重要)
3.结合配置文件使用byName/byType方式自动装配
3.1 <bean id="person" class="com.lmy.entity.Person" autowire="byName/byType"></bean>
3.2 使用注解:@Autowired(只按照byType,Spring注解) 多个bean时结合@Qualifier注解指定name
3.3 使用@Resource(默认byName,找不到也可byType)注解 J2EE注解
使用注解时使用配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       #添加下面的约束#
       xmlns:context="http://www.springframework.org/schema/context"
       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
                           http://www.springframework.org/schema/context 
                           http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 确定使用注解  -->
    <context:annotation-config></context:annotation-config>
    <!-- 自动扫描指定的包 -->
    <context:component-scan base-package="cn.spring.demo"></context:component-scan>
</beans>
3.4 注解说明
 @Component 放在类上,说明这个类被Spring管理了,相当于bean
 	衍生注解:@Controller @Service @Mapper
 @Nullable 字段标记了这个注解,说明这个字段可以为null
 @Value  相当于<property name="id" value="1"/>
 @Import 相当于配置文件中的<import>,代表着把多个配置类合并
4.代码方式进行装配(不再需要配置文件,SpringBoot的最常见方式)
@Configuration+@Bean注解配合使用,代表是一个配置类,方法注册为一个bean,方法返回值就是<bean>标签的class
//注解方式获取Spring上下文对象
ApplicationContext context1 = new AnnotationConfigApplicationContext("com.lmy.*");
Person person1 = (Person) context.getBean("getPerson");//getBean方法有@Bean注解
System.out.println(person1);

#AOP 面向切面编程
 ##代理模式:静态代理和动态代理:提取公共业务,方便扩展
 1.静态代理:抽象角色、代理角色、真实角色、用户角色;
 代理角色代理真实角色向用户角色提供使用,比真实角色增加附加功能
 2.动态代理:代理角色不用自己写,是动态角色(基于反射实现)
 	基于接口:JDK动态代理。基于类:CGLIB动态代理
 	java字节码:javasist JBoss容器使用,Tomcat不用
 2.1 JDK动态代理:InvocationHandler(实现了这个接口)、Proxy(提供静态方法创建代理对象)
 public class ProxyLearn implements InvocationHandler {
   
    private Object target;
    public void setTarget(Object target) {
   
        this.target = target;
    }
    public Object getProxy(){
   
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   
        //执行方法
        Object invoke = method.invoke(target, args);
        return invoke;
    }
}
##AOP 核心:使用代理模式,代理对象为原来的业务。切面、切点
<dependencies>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.4</version>
    </dependency>
</dependencies>
1.xml配置(第一种自定义类;第二种定义一个切面类)
 <bean id="diy" class="com.diy.DiyPointcut">
    </bean>
    #第一种
    #<aop:config>
     #   <!--切入点:expression:表达式,execution(要执行的位置)-->
    #    <aop:pointcut id="point" expression="execution(* com.service.*.*(..))"/>
    #    <!--执行环绕-->
     #   <aop:advisor advice-ref="log" pointcut-ref="point"/>
     #   <aop:advisor advice-ref="afterlog" pointcut-ref="point"/>
    #</aop:config>
    #第二种
    <aop:config>
        <!--自定义切面-->
         <!--配置aop-->
        <aop:aspect ref="diy">
            <!--切入点-->
            <aop:pointcut id="point" expression="execution(* com.service.*.*(..))"/>
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
2.基于注解
@Aspect//标注这个类是一个切面
@Order(1)//越小优先级越大
@Component
public class Annotation1 {
   
    @Before("execution(* com.lmy.proxylearn.*.*(..))")
    public void before(){
   
        System.out.println("before");
    }
    @After("execution(* com.lmy.proxylearn.*.*(..))")
    public void after(){
   
        System.out.println("after");
    }
    //在环绕增强中,我们可以给一个参数,代表我们要获取切入的点
    @Around("execution(* com.lmy.proxylearn.*.*(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
   
        System.out.println("around");
        Object proceed = joinPoint.proceed();
        System.out.println("after around");
        return proceed;
    }
}

3.整合mybatis

<dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <version>5.1.47</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.4</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.2</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>
<!-- 读取不到mybatis的xml sql文件-->
   <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>
<!-- ************mybatis xml 配置*******************-->
<configuration>
    <typeAliases>
        <package name="com.pojo"/>
    </typeAliases>
<settings>
        <!-- 下划线转驼峰-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--开启二级缓存  -->
        <setting name="cacheEnabled" value="true"/>
    </settings>
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事务管理 -->
            <transactionManager type="JDBC" />
            <!-- 数据库连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://192.168.6.128:3306/lmy_test" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/test/testMapper.xml"/>
    </mappers>
</configuration>

   <!--*******************spring xml 配置**************-->

 <!--data source-->
    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://111.230.212.103:3306/mybatis?userSSL=true&amp;
                userUnicode=true&amp;characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value="hdk123"/>
    </bean>
    <!--sqlsession-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="datasource" />
        <!--bound mybatis-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:com/mapper/UserMapper.xml"/>
    </bean>
    <bean id="userMapper2" class="com.mapper.UserMapperIml2">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
    </bean>

    <!--声明式事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <constructor-arg ref="datasource" />
    </bean>

    <!--结合aop实现事务置入-->
    <!--配置事务的类-->
    <tx:advice id="tx1" transaction-manager="transactionManager">
        <!--给哪些方法配置事务-->
        <!--配置事务的传播特性-->
        <tx:attributes>
            <tx:method name="add" propagation="REQUIRED"/>
            <tx:method name="delete" propagation="REQUIRED"/>
            <tx:method name="update" propagation="REQUIRED"/>
            <tx:method name="*" propagation="REQUIRED"/>
            <tx:method name="query" read-only="true"/>
        </tx:attributes>
    </tx:advice>

    <!--配置事务切入-->
    <aop:config>
        <aop:pointcut id="txpointxut" expression="execution(* com.mapper.*.*(..))"/>
        <aop:advisor advice-ref="tx1" pointcut-ref="txpointxut"/>
    </aop:config>

4.Spring相关面试题

1.Spring 如何创建bean对象的?Bean的生命周期?

#调用类的构造方法---->实例化对象(原对象)---->依赖注入---->初始化前---->初始化---->初始化后(AOP出代理对象,其他处理等)---->放入Map单例池---->Bean对象-->销毁
1.1 #调用类的构造方法:多个构造方法首先会判断是否有@Autowired指定构造方法,再看是否有无参构造方法,都没有则报错;只有一个有参的就会调用这个方法;调用有参时会传入参数对象,找到该对象是(先byType后byName)
1.2 #初始化前:@PostConstruct注解方法
1.3 #初始化 :有没有实现initializingBean接口进行自定义初始化
1.4 #初始化后:如果AOP产生了代理对象就会把代理对象放入单例池,没有则放入原对象;注意:生成的代理对象里面的@Autowired并没有没有值(即没有依赖注入到代理对象),而是实例化了一个原对象,直接调用对象的方法
1.5 # Map单例池:<beanName,Bean对象>所以beanName是唯一的(一级缓存)
1.6 Spring的启动过程
#先进行扫描得到所有的BeanDefinition对象,并存入Map中;然后筛选出非懒加载的单例BeanDefinition进行创建Bean,对于多例的bean是每次使用的时候创建;通过BeanDefinition创建Bean就是Bean的生命周期,创建完成之后发布一个容器启动事件,则结束整个流程
	1.解析Bean配置信息,將配置信息转换为BeanDefinition对象,注册到BeanDefinitionRegistry中。
	2.执行所有的BeanFactoryPostProcessor的postProcessBeanFactory()方法对Bean工厂信息进行修改,包括修改或新增BeanDefinition对象。注意:如果需要控制BeanFactoryPostProcessor的执行顺序需要实现PriorityOrdered接口,getOrder()方法返回的值越小,执行优先级越高。
	3.通过BeanDefinition对象实例化所有Bean,注入依赖。
	4.执行所有BeanPostProcessor对象的postProcessBeforeInitialization()方法。
	5.执行Bean的初始化方法,例如InitializingBean接口的afterPropertiesSet方法,或init-method属性指定的方法。
	6.执行所有BeanPostProcessor对象的postProcessAfterInitialization()方法。


2.Spring怎么解决循环依赖?
#创建bean对象的第一步,使用有参构造方法时,需要一个bean,会在map单例池中寻找,找不到则创建,两个bean都需要另一个,即产生了循环依赖问题:①使用三级缓存解决循环依赖②使用@Lazy注解
2.1 为什么不用二级缓存解决
#二级缓存可以解决循环依赖的问题,但是不能解决aop场景下的循环依赖,这样注入到其他b
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没有什么是应该

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值