Java学习篇——Spring中的IOC和AOP(建议去了解反射、Xml、23中设计模式,MVC设计)

Spring是什么?

  • 学习之前 自己在idea中新建一个md文档      (记录   ——xml依赖  记录——注解)
  • Web开发中的一阵春风,解决任何java应用开发
  • 2002年 interface21  Spring前身。2004年Spring出现
  • 概念:一个开源免费的、轻量级的控制反转和面向切面的框架


  • 优点:

    • 1、开源免费
    • 2、轻量级(只需要加依赖就行),非侵入性(不用更改业务源代码)
    • 3、控制反转和面向切面
    • 4、支持对事务的操作,对框架整合的支持
  • 缺点:

    • 体系庞大。配置大多。

包含  7大模块  :Spring的七大模块,以及每个模块的作用_Lilia_T的博客-CSDN博客_spring七大模块

IOC:控制反转

ioc是一种编程思想:将主动编程变为被动接受。 对象的 交给Spring创建   管理  装配。

控制:谁来控制对象的创建,传统的程序的对象时由程序本身来创建,使用Spring时,对象由Spring创建。

反转:程序本身不创建对象,而变成被动接受对象。

依赖注入:使用set方法注入属性值


Spring怎么创建对象

        1、XML文件(Bean标签)

        2、注解    (5个注解)

Spring 依赖注入:

        1、xml  (bean标签的其他属性   两种 set  构造器注入 )

        2、继基于接口的注解注入 
问题:有几种注入方式?3种

先创建Maven工程,在配置文件中加入依赖。Spring——web MVC   使用MVC是一次性的加载多个依赖。 (后面项目可以使用创建spring工程)


1、XML文件的方式


怎们创建对象????????????


*****实现过程——反射:  找XML文件,拆解XML文件,反射创建,交给Spring容器管理。
 

官方的创建对象学习地址:

Core Technologies

Spring 配置包含容器必须管理的至少一个,通常是多个 bean 定义。基于 XML 的配置元数据将这些 bean 配置为<bean/>顶级元素内的<beans/>元素。

自定义XML文件将以下代码赋值进入,将官方定义的<bean>删除  使用自己想建立的对象。

<?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">

    <bean id="..." class="...">  
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions go here -->

</beans>

java代码  main方法中   获取配置文件的类对象。   

作用:加载Spring  xml文件中的Bean    可以写多个xml文件。

ApplicationContext context = 
new ClassPathXmlApplicationContext("services.xml", "daos.xml");
  • 自定义对象时需要有自己的类,spring中也有自己的一些对象。
自定义类
public class user {
    private String username;
    
    user(){
    username=“nihao”
    }

    //get set  方法
}

  • 创建对象默认无参构造方法创建(官方还有其他方法创建可以去官方网址参考)  类属性赋值必须有 set方法
  • 有参构造创建对象时:根据参数顺序创建、根据参数类型创建、根据参数名称创建
  • set方法注入下面说


对象创建的时机:?????????获取  (xml文件)上下文的时候


获取对象:getBean()




xml文件的配置  标签:

        <alias/>别名

     

<alias name="fromName" alias="toName"/>
name:bean的id    alias:bean的别名   获取的时候用

        <bean> 创建对象
 

<bean id="exampleBean" class="examples.ExampleBean"/ name=" a, b ,c" scope="">
name :也是别名   可以写多个    
scope:作用域:默认单例

更多属性  自己查看

<import>导入其他xml   resources里面写路径。




 




依赖注入:

DI  依赖注入是IOC 的实现  办法。

依赖:创建对象的过程依赖于 Spring容器

注入:对象的属性 通过Spring容器注入。

官方解释:

        依赖  对象的属性

        注入:创建对象时将属性注入赋值

构造器注入(上面已说)、set注入、拓展注入


set注入

被创建对象时注入属性的类———— 

—— Set注入根据属性名注入

普通值注入

<bean id="xiaoming" class="cn.zhangyongqi.user">
<property name="zhang"  value="good">
</bean>

根据属性名字 注入。

bean注入  Address自定义的类型   下面赋值给Address创建对象 ,上面将对象注入给Student类的属性。——(自动装配的前身  现在是主动装配,)

bean注入  数组类型

bean注入  list类型

 bean注入  Map类型

  bean注入  Set类型

 bean  null值注入

 bean  proerties类型注入


拓展注入:cp命名空间注入

  • p对应set
  • c对应构造器


p  先导入  p命名空间的依赖项    property

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"      p命名的依赖性
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    
    <bean name="classic" class="com.example.ExampleBean">
        <property name="email" value="someone@somewhere.com"/>
    </bean>

    两种注入的属性值  效果相同
    <bean name="p-namespace" class="com.example.ExampleBean"
        p:email="someone@somewhere.com"/>
</beans>

c 命名空间,先导入依赖项  c:会出现构造器参数出现   constructor

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
c命名空间的依赖项    
xmlns:c="http://www.springframework.org/schema/c"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="beanTwo" class="x.y.ThingTwo"/>
    <bean id="beanThree" class="x.y.ThingThree"/>

    <!-- traditional declaration with optional argument names -->
    <bean id="beanOne" class="x.y.ThingOne">
        <constructor-arg name="thingTwo" ref="beanTwo"/>
        <constructor-arg name="thingThree" ref="beanThree"/>
        <constructor-arg name="email" value="something@somewhere.com"/>
    </bean>
    两种注入方法效果相同  下面更方便。
    <!-- c-namespace declaration with argument names -->
    <bean id="beanOne" class="x.y.ThingOne" c:thingTwo-ref="beanTwo"
        c:thingThree-ref="beanThree" c:email="something@somewhere.com"/>

</beans>


作用域:Scope           

(作用域是什么意思,单例原型 是什么     23种设计模式【狂神说Java】单例模式-23种设计模式系列_哔哩哔哩_bilibili

*****

默认单例的,怎么取都只有一个相同对象。

<bean id="accountService" class="com.something.DefaultAccountService"/>

<!-- the following is equivalent, though redundant (singleton scope is the default) -->
<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>



加标签
scope="singleton"

原型的:

<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>

原型
scope="prototype"

其余的在web应用里面使用。.....(先不聊了)


基于XML的自动装配

  •  自动注入是Spring满足bean依赖的一中方式
  • Spring会在上下文中寻找,并给bean装配属性

Spring中有三种装配模式

  • xml中的显示配置  、(显示是直接给值上面的set注入  隐式是去找值)
  • java中的显示配置    (直接给值)
  • 隐式的自动装配bean配置  *****



xml的隐式装配***************************byName  —— byType

spring加载3个类  得到3个对象  人 狗 猫     人类中有猫和狗的属性     下面主动为属性注入了。

——byName 根据Spring容器中的bean ID去找  和需要装配的属性(set方法注入)的名称。

——byType  根据Spring容器中的bean ID去找  和需要装配属性类型。


使用注解实现自动装配

Core Technologies


使用注解须知

        导入约束

        配置注解支持

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    

xmlns:context="http://www.springframework.org/schema/context"
    
约束
xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    注解支持
<context:annotation-config/>

</beans>

@AutoWired  默认byType  类型注入  找不到根据byName(bean id) (required 两个值   true自动装配   false放弃自动装配 )

@Resource  根据名称再根据类型
当需要创建某个类的对象到Spring容器里面时,给对象的属性赋值时将@AutoWired注解在类属性上。

也可用在set方法上  一样的赋值。

用在属性上时可以没有Set方法。(反射  暴力注入)   ——(题外话:Lombok注解可以不写set get方法)

@Qualifier(value=“bean的id名”) 一般写在@AutoWired的下面   表示类型找不到按beanid找。

@Nullable  注解    用在构造器注入时  可以允许null


2、使用注解(装配对象)实现开发:

Spring4之后使用注解 

****配置bean需要 导aop的包  上面导依赖时已经包含了。

****需要注解支持的标签 

 

——使用XML扫描。
加标签

扫描根包下的bean   带了组件注解的类才能扫描。
<context:component-scan base-package="cn.te.zhang.entity">

组件注解  加在类上。

  •        @Componet:组件的意思——通用加载bean的注解
    • @Service:用在业务类上
    • @Controller:控制器上
    • @Repository: 数据存取类    (DAO)


——使用  纯java类  扫描配置对象。

    • 另外后面会用到不用XML配置,在类上使用@Configuration  表示他是配置类。
    • 两种实现形式。     将类作为容器     将包作为容器
    • 将类作为容器:加了@bean注解的方法的返回值就是对象   @bean注解可以更改bean的默认名字(方法名),获取bean时就是根据方法名去掉get 获取。前提是User类加了组件注解   类比xml返回值为bean标签的class 属性   方法名相当于 id属性。
    • 将包作为容器:  配置类就是当加载此类时 ,工作将包下的加了注解主键的类放到容器里面。
    • @ComponentScan(根包:要加载进Spring容器里面的)  ,加载配置类时就会扫描加载根包下的类。
    • @Configuration    配置类注解
      @ComponentScan({"cn.tedu.spring","java"})  扫描注解
      @import(类/包)           导入其他配置类注解
         
      public class xxxconfig(){
          
      }

    • 配置类  一般命名使用xxx+config



AOP:面向切面编程


先讲代理模式:(23设计模式)

        AOP的底层就是代理模式的实现

        什么是代理模式?  需要某些代理对象帮助完成某些事。

        分类

                静态代理:一个代理对象对应一个真实对象

                动态代理:

 



静态代理


例子详解:

 角色分析:

        抽象角色:(接口或抽象类实现)这里为出租行为   

        真实对象:房东   被代理的角色

        代理对象:代理真实对象的一些操作,再加自己的附属操作

        客户:         访问代理对象的人

代码实现:

抽象角色  出租

真实角色    房东   被代理的角色   要实现抽象对象  出租行为

代理角色:中介    也要实现抽象对象  重写出租行为时  使用房东 的出租行为。 

客户:  用户租房的人。   为什么直接new 了房东 ?演示 ,,  实际可用反射注入到代理的构造方法中

 

代理对象脱离 真实对象  可以自己添加行为   (service  层的行为 )不用改变真实对象

还是调用  rent方法时  结果不同

 

 

优点:

        可以使真实角色更加存粹

        公共业务交给代理实现

        公共业务发生扩展更加方便管理

缺点:

        一个真实对象需要new一个代理对象

动态代理:

        1、与静态代理的角色一样

        2、代理关系不是写死的   一对一的,根据传入改变,代理角色动态生成

        3、分类:

                基于接口 : jdk   

                基于类 :   cglib(了解jvm比较麻烦)

                字节码:   javasist

需要了解两个类(为生成代理对象执行方法。)

        Proxy   代理对象

        InvocationHandle   调用处理的接口

InvocationHandle 源码说明文档   

 invoke方法 (代理对象调用真实对象时会利用反射机制调用此方法。)

参数:[ 代理的对象   方法对象 (代理对象执行的方法)  方法参数   (前面方法的参数,因为有重载 ,根据参数判定执行哪一个) ] 反射实现。  

Proxy 的源码说明文档

 里面有一个静态方法可以生成代理对象(可以不强转   直接用Object接受)

参数:   (真实角色的类路径      抽象角色(出租行为)   执行invoke方法的对象)

 

代码实现动态代理:

       

下面为生成代理对象和执行方法的工具类   为什么写?   将方法封装。不然每次使用前得

用匿名内部类创建一个执行invoke方法的对象(实现InvocationHandle接口,等下传到Proxy静态方法的参数里面)。

使用Proxy静态方法得到代理对象,代理对象会使用匿名内部类的重写的invoke方法

创建一个 工具类

上述静态代理的         出租rent接口  和真实角色 房东HOst不变(那两个类或接口不变)

客户   用户、

好处:

        包含静态代理的好处

        一个动态代理类可以代理 一个接口(一般 表示某些行为业务)

        一个动态代理类可以代理多个实现接口的类。(可以得到多个房东)




AOP:面向切面编程


Spring 的关键组件之一是 AOP 框架。虽然 Spring IoC 容器不依赖 AOP(这意味着如果您不想使用 AOP,则无需使用 AOP),AOP 补充了 Spring IoC 以提供非常强大的中间件解决方案。

面向切面编程;对oop面向对象编程的补充。  

通过预编译的方式和运行期间动态代理   实现程序功能的统一维护的一种技术

函数式编程的衍生范型,

aop可使业务逻辑各个部分进行隔离,从而使得业务逻辑之间耦合度降低,提高程序可复用性,同时提高开发效率。

pom文件加依赖


方式1 
使用Spring接口   实现

准备抽象角色(行为)



真实角色(房东)


增强方法  切入方法



 
执行增强方法  在方法执行前

重写before方法  参数对应动态代理的invoke方法参数
Method   代理对象执行的方法

args   方法参数

Object    代理对象(应该说真实角色对象 )

 执行增强方法  在方法执行后

参数跟上述一样

 
 


配置xml

导入AOPjar包

将 这几个类导入 spring容器、配置aop。     需要切入点   切入方法


测试     

获取xml、文件  、(得到Spring容器)

得到代理对象(相当于一个没有类名的对象   只是实现了接口)(已经不是接口了   )(需要向上造型  变成接口对象)

执行方法


方式2  使用自定义类作为切面实现

 

将类作为切面 

设置xml文件  aop  上一种方式的bean不变
diy类为切面   可以在 切入点(方法)

切入方法。

 测试

比较简单,但是可操作性没上面的高 ,因为上面的方法参数多。
 


使用注解实现:继续使用类做切面(只是将xml文件配置换为注解) 

        和上面一样自定义类  做切面

        切点前  切点后 切点环绕

切点环绕方法执行的时机    参数jp为执行的切入点



        配置xml  将自定义类注册为Spring对象、开启注解支持

 测试和刚刚的一样

 注解的缺点:需要多次配置切点  也是一个好处。



3、整合Mybatis
       

步骤:

      1、导包:  junit 、       mybatis 、       mysql 、       spring、        aop织入、 

spring jdbc      mybatis—spring(中文文档  还有 mybatis-spring-boot-start)    (和谁整合杠谁)   

      2、编写配置文件

      3、测试
 



回忆mybatis——————

        编写实体类

        编写核心配置文件

        编写mapper接口

        编写mapper.xml

        测试

核心配置文件——

开发环境

type  哪种管理

value 驱动

url连接到哪个库、时间 、 安全连接、编码、

连接数据库 :      测试

mybatis——spring整合

        


spring中声明事务:业务一般都需要声明事务。

mybatis-spring –事务管理的官网文档

MyBatis-Spring 借助了 Spring 中的 DataSourceTransactionManager 来实现事务管理。

        声明式事务:AOP 横切进去的

        编程式事务:需要在代码中声明事务的管理

      

编程式:

public class UserService {
  private final PlatformTransactionManager transactionManager;
  public UserService(PlatformTransactionManager transactionManager) {
    this.transactionManager = transactionManager;
  }
  public void createUser() {
    TransactionStatus txStatus =
        transactionManager.getTransaction(new DefaultTransactionDefinition());
    try {
      userMapper.insertUser(user);
    } catch (Exception e) {
      transactionManager.rollback(txStatus);
      throw e;
    }
    transactionManager.commit(txStatus);
  }
}

声明式事务:——————————————————————————————————— 

一、配置事务管理器的bean   DataSourceTransactionManager

二、导入TX 约束 tx:advice配置事务通知(对应下面的配置注解支持)

        transaction-manager  使用的事务管理器

        tx:attribute 配置使用事务的方法 

        tx:method 方法名  单个方法所有方法

        propagation:事务的传播级别  7种

三、AOP织入:

        aop:config 配置切入

        配置切入点   执行位置  包下的类下的所有方法(..)代表参数

        aop:advice 配置事务    pointcut-ref  配置切入点

 

配置事务管理代码

传播级别:

———————————————————————————————

注解支持

基于注解方式来进行声明式事务的操作会更加简单,在实际开发中我们也会用的比较多,我们基于以上案例继续完成

@Transactional 注解只应用到 public 修饰的方法上,在 protected、private 修饰的方法上都不会起作用

1)配置事务管理器(同上1)
<!-- 1.配置事务的管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!-- 指定要对哪个数据库进行事务操作 -->
    <property name="dataSource" ref="dataSource"></property>
</bean>
1
2
3
4
5
2)注释掉事务的其他配置,开启事务注解
<!-- 2.开启事务的注解 -->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
1
2
完成之后的配置文件问:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
     xmlns:aop="http://www.springframework.org/schema/aop"
     xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

       <!--指定注解扫描包路径-->
    <context:component-scan base-package="com.oak"/>

       <!-- 导入资源文件 -->
      <context:property-placeholder location="classpath:dbutil.properties"/>
      <!-- 配置dbcp连接池参数 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
   destroy-method="close">
        <property name="driverClassName" value="${driver}" />
        <property name="url"
            value="${url}" />
        <property name="username" value="${user}" />
        <property name="password" value="${password}" />
        <!-- 连接池启动时的初始值 -->
        <property name="initialSize" value="${initsize}" />
        <!-- 连接池的最大值 -->
        <property name="maxActive" value="${maxsize}" />
        <!-- 最大空闲值。当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
        <property name="maxIdle" value="${maxIdle}" />
        <!-- 最小空闲值。当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
        <property name="minIdle" value="${minIdle}" />
    </bean>
    <!-- 配置 Spring 的 jdbcTemplate -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>    
    </bean>
    
    <!-- 1.配置事务的管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 指定要对哪个数据库进行事务操作 -->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!-- 2.开启事务的注解 -->
    <tx:annotation-driven transaction-manager="transactionManager">    </tx:annotation-driven>
</beans>

spring boot  直接使用@Transactional注解就行。

        

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值