Spring 框架

什么是框架?

框架就是一种高度抽取重复代码的设计,具有高可用性重用性,框架其实也是一个半成品软件。

Spring 框架

spring是一个非侵入性的轻量级框架,说 spring是轻量级并不是指 spring 的 jar包和其依赖(源码)是少量的,反而spring是一个庞然大物,包罗万象,而是指spring是非侵入性的,

Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架(SpringMVC)。

spring 框架的好处

1、非侵入式设计

Spring是一种非侵入式(non-invasive)框架,它可以使应用程序代码对框架的依赖最小化。

2、 方便解耦、简化开发 (IOC/DI)

Spring就是一个大工厂,可以将所有对象的创建和依赖关系的维护工作都交给 Spring 容器管理,大大地降低了组件之间的耦合性。

3、支持 AOP

Spring 提供了对 AOP 的支持,它允许将一些通用任务,如安全、事务、日志等进行集中式处理,从而提高了程序的复用性。

4、支持声明式事务处理

只需要通过配置就可以完成对事务的管理,而无需手动编程。

5、方便程序的测试

Spring提供了对 Junit4 的支持,可以通过注解方便的测试 Spring程序。

6、方便集成各种优秀框架

Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持。

7、降低Java EE API的使用难度

Spring对Java EE开发中非常难用的一些API(如:JDBC、JavaMail等),都提供了封装,使这些API应用难度大大降低。

spring的体系结构

Spring是一个分层框架,由七个定义良好的模块组成。Spring模块构建在核心容器之上,核心容器定义了创建,配置,管理bean的方式。

 进入正题学习:

1.1 核心容器 beanFactory

核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory ,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开 ( 工厂方法 ) 。 简单来说就是将 bean 的创建由程序内部交给了 Spring 容器

BeanFactory使spring成为一个容器,

spring容器:工厂模式+单例模式的实现

1.2 ApplicationContext 上下文

Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。 Spring 上下文包括企业服务,例如JNDI 、 EJB 、电子邮件、国际化、校验和调度功能。

applicationContext.xml:spring核心配置文件-->上下文(BeanFactory的外在体现)

ApplicationContext 使 spring成为一个框

1.3 

spring AOP

        通过配置管理特性, Spring AOP 模块直接将面向切面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP 。 Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP ,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。

Spring DAO

        JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。 Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构

spring ORM

        Spring 框架插入了与若干个 ORM 框架整合的接口,从而提供了 ORM 的对象关系工具,其中包括 JDO 、 Hibernate 和 iBatis SQL Map 。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。

Spring Web模块

        Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以, Spring 框架支持与 Jakarta Struts 的集成。 Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。

Spring MVC框架

        MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口, MVC 框架变成为高度可配置的, MVC 容纳了大量视图技术,其中包括 JSP 、 Velocity 、 Tiles 、 iText 和 POI 。

1.4 spring的两大核心

DI / IOC  -  依赖注入 / 控制反转 

依赖注入:将依赖对象的创建和赋值(装配)由程序内部交给了外部容器,并将创建的依赖对象注入程序内部,达到完全解耦的目的

是指工程中需要的组件无须自己创建,而是依赖于外部环境注入。

IOC是一种软件设计思想,DI是这种软件设计思想的一个实现,DI是spring的核心机制

 

1.5 AOP面向切面编程

springAOP是spring DI的补充

概述:简单的说它就是把我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的基础上,对我们的已有方法进行增强,比如 日志管理,事务管理,权限管理等

实现原理:代理模式

2 spring框架搭建

2.1基础环境搭建的步骤

2.1.1基础环境

  • 1创建SE项目-->maven

  • 2导入spring基础依赖(pom.xml)

      <properties>
            <!-- spring 版本号 -->
            <spring.version>5.3.23</spring.version>
        </properties>
        <!--引入spring基础依赖-->
        <dependencies>
            <!-- 此依赖会关联引用Spring中的所有基础jar包 -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>
        </dependencies>

  • 3在resources目录下新建一个spring核心配置文件 applicationContxt.xml

  • application中只需将要管理进Spring容器的类通过<bean>标签管理进Spring容器

  • 后面会讲这个bean的实例化原理

application.xml 示例

<?xml version="1.0" encoding="UTF-8"?>
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--管理UserDao进spring容器-->
    <bean id="userDao" class="com.neuedu.demo.dao.UserDaoImpl"></bean>
    <!--id 为 bean 的唯一标识,class是要管理进spring的类的全限定类名-->
    <!--后面会讲这个bean的实例化原理-->
</beans>
  • 4 运行测试

  • public static void main(String[] args) {
    //        加载applicationContext.xml,获取BeanFactory容器
            BeanFactory factory=new ClassPathXmlApplicationContext("applicationContext.xml");
    //          通过getBean(bean的id)方法获取容器中的实例
            IUserService userService=(UserServiceImpl)factory.getBean("userService");
            userService.findUser();
        }

3.1spring中bean的基本原理

spring实例化bean的过程(反射是框架的灵魂)

 

4.1获取spring容器的三种方式

 

 

   

  

 

 applicationContxt.xml:

<!--依赖注入的三种方式
    构造方法注入
    属性注入(设值注入)
    接口注入:侵入性强

 -->
<!-- ========================================构造方法注入=======================================-->
 <bean id="userDao" class="com.wudagai.springtest.dao.UserDaoImpl"></bean>
 <!--
    Student student=new Student("zhangsan",20,90.0);
     public Student(String stuName, Integer stuAge, Double grade)
   <constructor-arg>构造方法的每一个参数,
    就是用构造方法注入时多个不同类型参数
    必要属性: ref 或 value
      ref:参数的类型是一个pojo(实体类)
      value:简单的类型  String和包装类型
    非必要属性:
        index:参数的索引,索引从0开始,就要给第几个参数进行赋值	 
        name:指定构造方法中的参数名
        type:指定参数转换的类型
    注意:依赖注入简单类型配置的时候都是String类型,
         但是spring中有许多类型转换组件,会将String类型转为参数对应的类型再进行赋值
         所以建议所有的成员变量都用包装类进行声明
 -->
 <!--<bean id="student" class="com.wudagai.springtest.pojo.Student">-->
   <!--<constructor-arg value="zhangsan"></constructor-arg>-->
   <!--<constructor-arg value="40"></constructor-arg>-->
  <!--<constructor-arg value="90.0"></constructor-arg>-->
 <!--</bean>-->

 <!--<bean id="student" class="com.wudagai.springtest.pojo.Student">-->
  <!--<constructor-arg index="1" value="20" ></constructor-arg>-->
  <!--<constructor-arg index="0" value="lisi"></constructor-arg>-->
  <!--<constructor-arg index="2" value="80.0" ></constructor-arg>-->
 <!--</bean>-->

 <bean id="student" class="com.wudagai.springtest.pojo.Student">
 <constructor-arg name="stuAge" value="20" type="java.lang.Integer" ></constructor-arg>
 <constructor-arg name="stuName"  value="lisi" type="java.lang.String"></constructor-arg>
 <constructor-arg name="grade"  value="81.0" ></constructor-arg>
 </bean>


 <!-- ========================================set方法注入 =======================================-->
  <!--
    <property >:设置属性
        必要属性: ref 或 value  name
         ref:参数的类型是一个pojo(就是要将哪个依赖注入)
         value:简单的类型  String和包装类型
         name:属性名->set/get方法去掉get/set剩下的英文单词首字母小写 比如setUserDao->userDao    setUserName->userName

  -->
 <bean id="student1" class="com.wudagai.springtest.pojo.Student">
  <property name="stuName" value="wangwu"></property>
  <!--<property name="userDao" ref="userDao"></property>-->
  <property name="userDao">
    <bean class="com.wudagai.springtest.dao.UserDaoImpl"></bean>
  </property>
 </bean>

5.2依赖注入的类型

<bean id="stu8" class="com.wudagai.springtest.pojo.Student">
       <!--简单类型-->
       <property name="stuName" value="zhangsan"></property>
        <property name="stuAge" value="20"></property>
       <!--pojo类型-->
        <!--<property name="minStudent" ref="min"></property>-->
        <property name="minStudent">
            <bean class="com.wudagai.springtest.pojo.MinStudent">
                <property name="minAge" value="20"></property>
            </bean>
        </property>
        <!--list集合-->
        <property name="stringList">
            <list>
                <value>zhangsan</value>
                <value>lisi</value>
                <value>zhangsan</value>
            </list>
        </property>
​
        <property name="minStudentList">
            <list>
                <ref bean="min"></ref>
                <bean class="com.wudagai.springtest.pojo.MinStudent"></bean>
            </list>
        </property>
       <!--set集合-->
        <!--private Set<String> stringSet;-->
        <property name="stringSet">
            <set>
                <value>zhangsan</value>
                <value>lisi</value>
                <value>zhangsan</value>
            </set>
        </property>
        <!--private Set<MinStudent> minStudentSet;-->
        <property name="minStudentSet">
            <set>
                <ref bean="min"></ref>
                <bean class="com.wudagai.springtest.pojo.MinStudent"></bean>
            </set>
        </property>
       <!--map集合-->
        <!--private Map<Integer,String> integerStringMap;-->
        <property name="integerStringMap">
            <map>
                <entry key="1" value="zhangsan"></entry>
                <entry key="2" value="lisi"></entry>
                <!--private Map<Integer,MinStudent> integerMinStudentMap;-->
                <!--<entry key="3">-->
                <!--<bean class="xxxxx"></bean>-->
                <!--</entry>-->
            </map>
        </property>
       <!--properties类型-->
        <!--private Properties properties;-->
        <property name="properties">
            <props>
                <prop key="url">jdbc://mysql:localhost:3306:test</prop>
                <prop key="driver">com.mysql.jdbc.Driver></prop>
                <prop key="username">root</prop>
                <prop key="password">123</prop>
            </props>
        </property>
    </bean>

5.3spring注解配置

spring的配置方式一共有三种

第一种(spring1.x版本):xml配置方式

场景:任何bean都可以使用xml配置,简单来说就是自定义业务场景的bean和基础配置还有第三方依赖的bean都可以通过xml配置后交由spring管理

<!--将UserDao管理进spring容器-->
<bean id="userDao" class="com.wudagai.springtest.dao.UserDaoImpl"></bean>
<!--将UserService进spring容器-->
<bean  id="userService" class="com.wudagai.springtest.service.UserServiceImpl">
<constructor-arg ref="userDao"></constructor-arg>
</bean>

第二种(spring2.x版本):注解方式

疑问:是用xml配置还是用注解配置?

场景:

自定义业务场景的bean和基础配置是用注解方式

第三方依赖的bean是用xml配置

第三种方式(spring3.x版本):javaConfig方式(java配置方式)

  • spring注解配置

    • 依赖于AOP,导入aop的依赖

    ①需要在applicationContext.xml中开启注解装配

    <!--=========================注解方式配置依赖注入=======================-->
     <!--开启注解装配-->
     <context:annotation-config />
     <!--将UserDao管理进spring容器-->
     <bean id="userDao" class="com.wudagai.springtest.dao.UserDaoImpl"></bean>
     <!--将UserService进spring容器-->
     <bean  id="userService" class="com.wudagai.springtest.service.UserServiceImpl"></bean>

    ②然后在需要注入的字段上使用注解@Resource(name="userDao")或者@Autowired

    public class UserServiceImpl implements IUserService {
     //@Autowired    
     @Resource(name="userDao")    
     private IUserDao userDao;
  • @Autowired

    按照类型找:根据字段类型匹配 spring容器中 bean的类型,如果匹配上了,spring自动将 bean注入字段中

    注意:

    ①如果通过字段的类型找到多个 bean,就会按照字段名配置bean的id,如果匹配上了,spring自动将 bean注入字段中,所以一般一个接口对应一个实现类即可

    ②如果找不到 bean就会报错,required = false属性配置该字段是否必须注入,false:不必须,true:必须,默认为 false

    ③可以通过@Qualifier(name)与 bean的 id匹配直接匹配

  • @Resource

    @Resource:作用跟@Autowired一样

    @Resource(name="xx") 作用跟@Qualifier(name)+@Autowired作用是一样的,根据name匹配bean的 id

     

     

     JDK动态代理核心代码:

  • /**
     * @author:
     * @date: 
     * @description:中间类
     * 由中间类生成代理对象
     */
    public class JavaProxyInvocationHandler implements InvocationHandler {
        /**
         * 中间类持有目标类对象的引用,这里会构成一种静态代理关系
         */
        private Object object; //目标对象
    
        private Object obj;//增强对象
    
        /**
         * 增强对象
         * @param obj
         */
        public JavaProxyInvocationHandler(Object obj){
          this.obj=obj;
        }
        /**
         * 动态生成代理类对象,Proxy.newProxyInstance
         * @return 返回代理类的实例
         * object:指定为哪一个目标对象生成代理对象
         */
        public Object newProxyInstance(Object object){
           this.object=object;
           return Proxy.newProxyInstance(
                   //指定代理对象的类加载器(获取目标对象的类加载器,代理对象由目标对象的类加载器进行加载)
                   this.object.getClass().getClassLoader(),
                   //代理对象需要实现的接口,可以同时指定多个接口(目标对象的接口)
                   this.object.getClass().getInterfaces(),
                   //方法调用的实际处理者,代理对象的方法调用都会转发到这里 保证invoke方法会被执行(代理对象每一次执行方法都会调用this.invoke())
                   this);
        }
    
        /**
         *
         * @param proxy
         * @param method 代理对象执行的方法(对象)--封装了方法的信息
         * @param args 方法的参数
         * @return 目标对象执行方法返回值
         * @throws Throwable
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            TranManager tranManager=null;//先定义好一个TranManager类型变量
            if(obj instanceof TranManager){//判断 obj 类型
                tranManager=(TranManager)obj;//向下塑型
            }
            tranManager.open();
            调用方法前
            Object result=method.invoke(object,args);//告诉目标对象执行核心业务方法result返回值
            调用方法后
            tranManager.close();
            return result;
        }
    }
    

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值