Spring注解&代理模式&AOP


Day40 Spring注解&代理模式&AOP

Spirng注解

什么是Spring

Spring是一款轻量级的DI/IOCAOP容器
Spring就是javabean的一个容器

Spring的两大核心

  • DI/IOC
    • IOC:控制反转 把当前应用对象中bean的创建权利都交给spring来管理 这种创建对象权利的反转就叫做控制反转
    • DI:依赖注入 我们把spring创建的bean 注入到指定接口的过程 这种方式就叫做依赖注入
  • AOP
    • 面向切面编程

编程思想

  1. 面向对象:强调的是一个封装性 模块化 更加符合人们的思想
  2. 面向过程:是C语言强调的一种编程思想
  3. 面向接口:其实就是指的在controller层注入service或service层中注入dao 定义的字段都应该是接口 定义接口的好处就是能够进行有效的解耦 扩展性更强一点 维护性更好
  4. 面向切面:它的作用其实就是对公共业务逻辑代码进行抽取 让代码进行解耦 让代码的扩展性更加强一点
  5. 面向百度:当掌握了基础知识以后 如果遇到做不来的功能 不可能一直看着 应该想尽一切办法进行解决 而在真实开发中 程序员都是面向百度 必应 google编程的

依赖注入

普通注入

<bean id="myBean" class="cn.itsource._01di.MyBean">
        <!--
        构造器注入,方案1:通过索引注入
        <constructor-arg index="0" value="122"/>
        <constructor-arg index="1" value="王天霸"/>

        方案3:通过构造器参数类型注入   最不推荐
        <constructor-arg type="java.lang.Long" value="22"/>
        <constructor-arg type="java.lang.String" value="西门吹雪"/>

        方案4: 通过构造器参数顺序注入   不推荐
        <constructor-arg value="33"/>
        <constructor-arg value="阮惊天"/>
        -->
        <!--方案2:通过构造器名字注入   最推荐使用-->
        <constructor-arg name="id" value="111"/>
        <constructor-arg name="name" value="李很弱"/>
        <!--
            属性注入
            value:给基本属性设置值
            ref: 只能用于对象,给对象设置值

        -->
        <property name="sex" value="true"/>
        <property name="salary" value="4000"/>
        <!--
        方案1:给对象注入值
        <property name="otherBean" ref="otherBean1"/>
        -->

        <!--方案2:给对象注入值-->
        <property name="otherBean">
            <bean class="cn.itsource._01di.OtherBean">
                <constructor-arg name="id" value="1"/>
                <constructor-arg name="name" value="洪熙官"/>
            </bean>
        </property>

        <!--给普通list注入值,元素非对象-->
        <property name="list">
            <list>
                <value>苗翠花</value>
                <value>方德</value>
                <value>雷老虎</value>
            </list>
        </property>

        <!--给普通list注入值,元素是对象-->
        <property name="otherBeanList">
            <list>
                <bean class="cn.itsource._01di.OtherBean">
                    <constructor-arg name="id" value="2"/>
                    <constructor-arg name="name" value="楚楚"/>
                </bean>
                <bean class="cn.itsource._01di.OtherBean">
                    <constructor-arg name="id" value="3"/>
                    <constructor-arg name="name" value="步惊云"/>
                </bean>
                <ref bean="otherBean1"/>
            </list>
        </property>
        <property name="set">
            <set>
                <value>4</value>
                <value>6</value>
                <value>5</value>
                <value>2</value>
                <value>3</value>
                <value>4</value>
            </set>
        </property>
        <property name="otherBeanSet">
            <set>
                <ref bean="otherBean1"/>
                <ref bean="otherBean1"/>
                <bean class="cn.itsource._01di.OtherBean">
                    <constructor-arg name="id" value="12"/>
                    <constructor-arg name="name" value="聂风"/>
                </bean>
            </set>
        </property>

        <!--
            properties的注入
            标准用法,推荐使用
        -->
        <property name="props1">
            <props>
                <prop key="jdbc.username">root</prop>
                <prop key="jdbc.password">123456</prop>
                <prop key="jdbc.driverClassName">com.mysql.jdbc.Driver</prop>
                <prop key="jdbc.url">jdbc:mysql:///crud</prop>
                <prop key="jdbc.autor">老孙</prop>
            </props>
        </property>

        <!--properties简写方式,不支持中文-->
        <property name="props2">
            <value>
                k1=v1
                k2=v2
                k3=v3
                k4=测试一把
            </value>
        </property>

       <!-- 数组标准注入
        <property name="arrays">
            <array>
                <value>How</value>
                <value>Are</value>
                <value>You</value>
            </array>
        </property>
        -->
        <!--简写方式-->
        <property name="arrays" value="SUN,FU,Lin"/>

    </bean>
    <bean id="otherBean1" class="cn.itsource._01di.OtherBean">
        <constructor-arg name="id" value="11"/>
        <constructor-arg name="name" value="金莲"/>
    </bean>
</beans>

XML方式自动注入

  • default-autowire=“byName” 根据名字自动注入 按照属性的名称 setXxx方法
  • default-autowire=“byType” 根据类型注入按照注入对象的类型,要求:类型只能配置一个实例
  • default-autowire=“constructor” 根据构造器注入

默认是类型注入
当你在指定的bean中告诉我们使用名字注入,类型注入就被覆盖了
<bean id="userService" class="cn.itsource._02xml_auto_di.service.impl.UserServiceImpl" autowire="byName" >

全注解注入

<context:component-scan base-package="cn.itsource._03all_auto_di"/>
开启组件扫描器 可以扫描到

  • @Controller 控制层
  • @Service 业务层
  • @Repository 持久层
  • @Component 非以上三层结构就贴此接口

以上四个注解源码都是一模一样的,都表示该类交给spring管理,它们仅仅代表一种标志而已
意思就是,如果你的类贴上了@Controller,就证明你这个类是属于控制层的

  • @Autowired 自动注入 特点:先根据类型注入,类型匹配不到,再根据名字注入

@Repository加了此注解意思就是
<bean id="userDaoJPAImpl" class="cn.itsource._03all_auto_di.dao.impl.UserDaoJPAImpl"/>
@Repository(“userDao”)
<bean id="userDao" class="cn.itsource._03all_auto_di.dao.impl.UserDaoJPAImpl"/>

@Autowired 与 @Resource的区别

  • @Autowired与@Resource都是依赖注入字段
  • @Autowired它是spring提供的注解
  • @Resource它是sun公司提供的注解


  • @Autowired它是先根据类型匹配,类型匹配不到则根据名字匹配
  • @Resource它是先根据名字匹配,名字匹配不到则根据类型匹配

以后注入对象的时候,推荐使用@Autowired 因为它和spring进行无缝集成
@Qualifier(“userDaoJPAImpl”) 查找名字为userDaoJPAImpl的bean注入到我这个接口中
@Resource(name = “userDaoJPAImpl”)

AOP

AOP底层是基于代理模式实现的

代理模式

在这里插入图片描述

分类

  1. 静态代理
  2. 动态代理
    • JDK动态代理 他只能代理有接口的实现类
    • CGLIB动态代理 他既能代理有接口的实现类 也能代理没有没有接口的类

AOP术语(了解)

  • 连接点(Joinpoint):程序执行的某一个特定位置,如类初始前后,方法的运行前后。而Spring只支持方法的连接点
  • 切点(Pointcut):切点可以定位到相应的连接点,一个切点可以定位多个连接点。
  • 增强(Advice):又被称为通知,完成逻辑的增强。
  • 目标对象(Target):增强逻辑织入的目标类。
  • 引介(Introduction):特殊的增强,为类添加一些属性和方法。
  • 织入(Weaving): 将增强添加到目标类的具体连接点上的过程。Spring使用动态代理织入。
  • 代理(Proxy):一个类(原类)被织入增强(逻辑)后,就产生一个结果类,称为代理类。
  • 使用AOP完成所有的功能都是通过代理类来完成的
  • 切面(Aspect):由切点和增强组成

配置

配置的时候一定要记住三个要素:何时,何地,做什么事
何时:在执行方法之前/之后/有异常…
何地:在哪些包中的哪些类的哪些方法上面执行
做什么事: 在UserServie中执行update方法之前添加日志

静态代理

静态代理的缺陷:
一个接口需要一个代理类
5个接口就需要5个代理类,太过于麻烦了,维护成本太高了

就相当于真实开发: 1个中介 只能代理1个房东 这是不合理的
正确合理的场景: 1个中介可以代理n个房东

AOP的配置

定义切点

  • cn.itsource._06aop_xml.service.IService.(…) 我要在cn.itsource._06aop_xml.service包下面所有以I开始并且Service结尾的类或者接口中所有的方法切上一刀

    第一个*: 任意返回值类型

    第二个*:I开头的Service结尾的类

    第三个*:类中的任意方法 (可变参数)

一般执行方法

<!--前置通知
<aop:before method="begin" pointcut-ref="pointcut"/>-->
<!--后置通知
<aop:after method="commit" pointcut-ref="pointcut"/>-->
<!--异常通知
<aop:after-throwing method="rollback" pointcut-ref="pointcut"/>-->
<!--最终通知
<aop:after-returning method="close" pointcut-ref="pointcut"/>-->

注意:当默认执行的顺序不是我们想要的,所以我们一般使用环绕通知,环绕通知就是自己去写业务逻辑
<aop:around method="around" pointcut-ref="pointcut"/>

aop的配置

	<aop:config>
    <!--
        定义切点
        *cn.itsource._06aop_xml.service.I*Service.*(..)  我要在cn.itsource._06aop_xml.service包下面所有以I开始并且Service结尾的类或者接口中所有的方法切上一刀
        第一个*: 任意返回值类型

    -->
    <aop:pointcut id="pointcut" expression="execution(* cn.itsource._06aop_xml.service.I*Service.*(..))"/>
    <aop:aspect ref="txManager">
        <!--前置通知
        <aop:before method="begin" pointcut-ref="pointcut"/>-->
        <!--后置通知
        <aop:after method="commit" pointcut-ref="pointcut"/>-->
        <!--异常通知
        <aop:after-throwing method="rollback" pointcut-ref="pointcut"/>-->
        <!--最终通知
        <aop:after-returning method="close" pointcut-ref="pointcut"/>-->

      <!--  注意:当默认执行的顺序不是我们想要的,所以我们一般使用环绕通知,环绕通知就是自己去写业务逻辑-->
        <!--环绕通知-->
        <aop:around method="around" pointcut-ref="pointcut"/>
    </aop:aspect>
</aop:config>
发布了54 篇原创文章 · 获赞 9 · 访问量 846

猜你喜欢

转载自blog.csdn.net/qq_40629521/article/details/104012694