Spring中的IOC、AOP到底是啥意思?耦合度又是什么!

1.Spring是什么?

       Spring是于2003年兴起的一个轻量级的Java开发框架,为了解决企业开发的复杂性。
       Spring的核心是控制反转(IOC)和面向切面编程(AOP)。Spring是可以在Java SE/EE中使用的轻量级开源框架。
       Spring根据代码的功能特点,使用IOC降低业务对象之间耦合度。IOC使得主业务在相互调用过程中,不用再自己维护关系了,即不用再自己创建要使用的对象了。而是由Spring容器统一管理,自动“注入”,注入即赋值。而AOP使得系统级服务得到了最大复用,且不用再由程序员手工将系统级服务“混杂”到主业务逻辑中了,而是由Spring容器统一完成“织入”。

2.Spring优点

Spring是一个轻量级、非侵入式、针对接口编程,解耦合、AOP编码支持、一站式框架为了解决企业级开发复杂性的框架
1.轻量级的
       Spring框架用的jar都比较小,一般在1M一下或者几百kb。Spring核心功能的所需的jar总共在3M左右。Spring框架运行占用的资源少,运行效率高。
2.非侵入式
       编写一些业务类的时候不需要继承spring特定的类,通过配置完成依赖注入后就可以使用,此时,spring就没有侵入到业务类的代码里。
3.针对接口编程,解耦合
       Spring提供了IOC控制反转,由容器管理对象,对象的依赖关系。原来在程序代码中的对象创建方式,现在由容器完成。对象之间的依赖解耦合。
4.AOP编程的支持
       通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP(面向对象)实现的功能可以通过AOP轻松应付,在Spring中,开发人员可以从繁杂的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
5.一站式框架
       Spring本身也提供了数据访问功能和web功能,以及可以很好的管理其他框架。

3.Spring体系结构

在这里插入图片描述
Core Container(核心管理器):
       Beans:管理Beans
       Core:Spring核心
       Context:配置文件
       ExpressionLanguage:SpEL表达式
AOP(切面编程)
AOP框架:Aspects
Data Access(数据库整合):
       JDBC,ORM,OXM,JMS,Transcation
Web(MVC Web开发):
       Web,Servlet,Portlet,Struts
Test(Junit整合):

4.Spring Hello World搭建

1.Maven 导入spring核心基础jar

<dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-context</artifactId>
     <version>5.2.2.RELEASE</version>
</dependency>

2.编写spring配置文件

<?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
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--
        bean:配置需要spring管理的类
        id:生成的对象名
        class:全类名
        name:对象别名,可以有多个
        scope:
        scope="singleton":单例的(单实例的),spring框架在他的容器中只创建了一个类的对象
                    在spring框架启动时就创建好了,在spring关闭时销毁
        scope="prototype":原型的(多例的),每次获得对象时(getBean()),spring框架才会去创建对象
        scope="request":为每次的http请求创建一个对象
        scope="sessioin":为每次回话创建一个对象
        scope="application":为一个应用程序创建一个对象
    -->
    <bean id="user" name="user1,user2" class="com.ff.spring.bean.User" scope="prototype"> </bean>
</beans>

3.编写一个User实体类

package com.ff.spring.bean;

import java.util.List;
import java.util.Map;

public class User {
    private String name;
    private Integer age;
    private List list;
    private Map map;

    public List getList() {
        return list;
    }


    public void setList(List list) {
        this.list = list;
    }

    public Map getMap() {
        return map;
    }

    public void setMap(Map map) {
        this.map = map;
    }

    public User() {
        System.out.println("User的无参构造");
    }

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
        System.out.println("User的有参构造");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", list=" + list +
                ", map=" + map +
                '}';
    }
}

4.测试spring

public class Test1 {

    @Test
    public void test(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        System.out.println("-----------------");
        User user = (User)applicationContext.getBean("user");
        System.out.println(user);
        System.out.println("-----------------");
        User user1 = (User)applicationContext.getBean("user1");
        System.out.println(user1);
        System.out.println("-----------------");
        User user2 = (User)applicationContext.getBean("user2");
        System.out.println(user2);
    }
}

5.IOC(控制反转)

        读作反转控制(Inverse of Control)更好理解,不是技术,而是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。
        IOC容器是具有依赖注入功能的容器,负责对象的实例化、对象的初始化、对象和对象之间依赖关系配置、对象的销毁、对外提供对象的查找等操作,对象的整个生命周期都是由容器来控制。我们需要使用的对象都由IOC容器进行管理,不需要我们手动通过new方式去创建对象,由IOC容器直接组装好,当我们需要使用的时候直接从IOC容器中获取。
正控: 若要使用某个对象,需要自己去负责对象的创建
反控: 若要使用某个对象,只需要从Spring容器中获取需要使用的对象,不关心对象的创建过程, 也就是把创建对象的控制权反转给了Spring框架。
在这里插入图片描述
目的: 降低耦合度。
(耦合度:耦合度就是某模块即类与其它模块之间的关联、感知和依赖的程度,是衡量代码独立性的一个指标,耦合度的强度依赖于以下几个因素:1.一个模块对另一个模块的调用;2.一个模块向另一个模块传递的数据量;3.一个模块施加到另一个模块的控制的多少;4.模块之间接口的复杂程度。)
(为什么要降低耦合度?耦合度很高的情况下,维护代码时修改一个地方会牵连到很多地方,如果修改时没有理清这些耦合关系,那么带来的后果可能会是灾难性的。)
底层实现方式: 解析xml/扫描注解标签+工厂模式+反射机制。

6.Spring Bean管理

1.基于xml配置方式
bean:配置需要spring管理的类
id:生成的对象名
class:全类名
name:对象名称,可以为多个
scope:
scope=“singleton”:单例的(单实例的),spring框架在他的容器中只创建了一个类的对象,在spring框架启动时就创建好了,在spring关闭时销毁;
scope=“prototype”:原型的(多例的),每次获得对象(getBean()),spring框架才会去创建对象;
scope=“request”:为每次的http请求创建一个对象,仅用于WebApplicationContext;
scope=“session”:为每次会话创建一个对象;
scope=“application”:为一个应用程序创建一个对象。

<?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
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--
        bean:配置需要spring管理的类
        id:生成的对象名
        class:全类名
        name:对象别名,可以有多个
        scope:
        scope="singleton":单例的(单实例的),spring框架在他的容器中只创建了一个类的对象
                    在spring框架启动时就创建好了,在spring关闭时销毁
        scope="prototype":原型的(多例的),每次获得对象时(getBean()),spring框架才会去创建对象
        scope="request":为每次的http请求创建一个对象
        scope="sessioin":为每次回话创建一个对象
        scope="application":为一个应用程序创建一个对象
    -->
    <bean id="user" name="user1,user2" class="com.ff.spring.bean.User" scope="prototype"> </bean>
</beans>

2.xml配置方式依赖注入
        指spring创建对象的过程中,将对象依赖属性(简单值,集合,对象)通过配置设置给该对象。
实现IOC需要DI做支持
注入方式:
        set方式注入;
        构造方法注入。

依赖注入方法:

<!--
        依赖注入:
            在IOC时(spring创建对象),对象中包含了属性,spring框架要将对象属性的值进行填充(赋值)
            这个动作就叫做依赖注入
        依赖注入方式1:通过属性的set方法注入值
    -->
    <!--
        创建对象的同时让spring为对象的属性赋值
    -->
    <!--<bean id="user" class="com.ff.spring.bean.User">
        <property name="name" value="jim"></property>
        <property name="age" value="23"></property>
        <property name="list">
            <list>
                <value>1</value>
                <value>2</value>
                <value>3</value>
            </list>
        </property>
        <property name="map">
            <map>
                <entry key="k1" value="v1"></entry>
                <entry key="k2" value="v2"></entry>
                <entry key="k3" value="v3"></entry>
            </map>
        </property>
     </bean>
-->
    <!--
        依赖注入方式2:通过属性的构造方法注入值
    -->
    <bean id="user" class="com.ff.spring.bean.User">
        <!--<constructor-arg name="name" value="bob"></constructor-arg>
        <constructor-arg name="age" value="22"></constructor-arg>-->
        <constructor-arg index="0" value="jim"></constructor-arg>
        <constructor-arg index="1" value="10"></constructor-arg>
    </bean>

3.注解方式实现
注解开发准备工作
注解需要的jar包
注解功能封装在AOP包中,导入Spring aop jar包即可
开启注解扫描:

<context:component-scan base-package="包名"> </context:component-scan>

注解创建对象:
@Component(value=“user)等于< bean id=“user” class=”">< bean>

@Component(value = "user")
public class User {
    private String name;
    private Integer age;
}

@Service

@Service(value = "userService")
public class UserService {

   /* @Autowired//byType根据属性类型匹配查找,不需要set方法
    @Qualifier(value = "userDao")//byName根据对象的value="对象名"名称查找*/

    @Resource//jdk中定义的注解实现
    UserDao userDao;
    public void save(){
        userDao.save();
    }
}

@Repository
以上注解都可以实现创建对象功能,只是为了后续扩展功能,在不同的层使用不同的注解标记
@Scope(value=“ptototype”) 原型
@Scope(value=“singleton”) 单例

4.注解方式注入属性
byType自动注入@Autowried
需要在引用属性上使用注解@Autowried,该注解默认使用按类型自动装配Bean的方式。使用该注解完成属性注入时,类中无需setter

@Service(value = "userService")
public class UserService {

    @Autowired//byType根据属性类型匹配查找,不需要set方法
    UserDao userDao;
    public void save(){
        userDao.save();
    }
}

byName自动注入@Autoeried与@Qualifier
需要在引用属性上联合使用注解@Autowried与@Qualifier。@Qualifier的value属性用于指定要匹配的Bean的id值

@Service(value = "userService")
public class UserService {

    @Autowired
    @Qualifier(value = "userDao")//byName根据对象的value="对象名"名称查找
    UserDao userDao;
    public void save(){
        userDao.save();
    }
}

JDK注解@Resource
spring提供了对jdk中@Resource注解的支持。@Resource注解既可以按名称匹配Bean,也可以按类型匹配Bean。默认是按名称注入。

@Service(value = "userService")
public class UserService {
    @Resource//jdk中定义的注解实现
    UserDao userDao;
    public void save(){
        userDao.save();
    }
}

byName注入引用类型属性
@Resource注解指定name属性,则name的值即为按照名称进行匹配的Bean的id。
5.注解与xml的对比
注解优点:方便,直观,高效(代码少,没有配置文件的书写那么复杂)。
注解缺点:以硬编码的方式写入java代码中,修改是需要重新编译代码的。
xml优点:配置和代码是分离的,在xml中做修改,无需编译代码,只需要重启服务器即可匠心的配置加载。
xml缺点:编写麻烦,效率低,大型项目过于复杂。

7.Spring JDBC

Spring是个一站式框架:Spring自身也提供了控制层的SpringMVC和持久层的Spring JdbcTemplate。
一、开发步骤:
1.下载Spring JdbcTemplate的jar包:

<!-- spring-jdbc --> 
<dependency> 
	<groupId>org.springframework</groupId> 
	<artifactId>spring-jdbc</artifactId> 
	<version>5.2.2.RELEASE</version> 
</dependency>
 <!-- 阿里数据源 --> 
 <dependency> 
	 <groupId>com.alibaba</groupId> 
	 <artifactId>druid</artifactId> 
	 <version>1.1.10</version> 
 </dependency>

2.导入属性文件

<context:property-placeholder location="config.properties"/>

3.管理数据源对象
spring管理与数据库链接(数据源)

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${url}"></property>
        <property name="driverClassName" value="${driver}"></property>
        <property name="username" value="${uname}"></property>
        <property name="password" value="${password}"></property>
</bean>

4.在配置文件中创建JdbcTemplate

<!--
        配置spring所提供的JdbcTemplate,用于向数据库发送sql
    -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

在类中获得JdbcTemplate对象,就可以直接使用

    @Autowired
    JdbcTemplate jdbcTemplate;

JdbcTemplate中的常用方法
execute:无返回值,可执行ddl,增删改语句;
update:执行新增,修改,删除语句;
queryFor***:执行查询相关语句。

		jdbcTemplate.update("insert into user(name,age,brithday) values('aaa',23,'2000-10-10')");
        jdbcTemplate.update("update user set name=?,age=?,brithday=? where id=?","bbb",22,"2000-10-11",14);
        jdbcTemplate.update("delete from user where id=?",14);
        /*execute()执行*/
        List<Map<String,Object>> peo = jdbcTemplate.queryForList("select * from user");
        Map<String,Object> aaa = jdbcTemplate.queryForMap("select * from user where id=13");

二、不使用AOP的开发方式
先定义好接口与一个实现类,该实现类中除了要实现接口中的方法外,还要再写两个非业务方法。非业务方法也称为交叉业务逻辑:

  • doTransaction():用于事务处理
  • doLog():用于日志处理
    然后,再使用接口方法调用它们,接口方法也称为主业务逻辑。
    案例:
    在这里插入图片描述

在方法中想要实现额外功能时,需要在业务代码中显示调用:
在这里插入图片描述
即使抽取一个工具类,将这些方法封装起来,依然还是需要显示调用
在这里插入图片描述
在这里插入图片描述

8.AOP

1.AOP概述
        AOP为Aspect Oriented Programming的缩写,翻译为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。
        AOP是OOP(面向对象)的延续,是软件开发中的一个热点,也是spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
        AOP、OOP在字面上虽然非常类似,但却是面向不同领域的两种设计思想。OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。
        而AOP则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各个部分之间低耦合性地隔离效果。这两种设计思想在目标上有着本质的差异。
面向切面编程的好处就是:减少重复,专注业务;
注意:面向切面编程只是面向对象编程的一种补充。
核心原理:
        使用动态代理的方式在执行方法前后或者出现异常的时候做加入相关的逻辑。
使用案例:
        事务处理:开启事务,关闭事务,出现异常后回滚事务
        权限判断:在执行方法前,判断是否具有权限
日志:在执行前进行日志处理
在这里插入图片描述
2.AOP的基本概念
连接点(Joinpoint):类中可以被增强的方法,这个方法就被称为连接点
切入点(pointcut):类中有很多方法可以被增强,但实际中只有add和update被增强了,那么add和update方法就被成为切入点(实际实现的连接点)
通知(Advice):通知是指一个切面在特定的连接点要做的事情(增强的功能)。通知分为方法执行前通知、方法执行后通知、环绕通知等。
切面(Aspect):把通知添加到切入点的过程叫切面
目标(Target):代理的目标对象(要增强的类)
代理(Proxy):项目标对象应用通知之后创建的代理对象
3.springAOP实现
        对于AOP这种编程思想,很多框架都进行了实现。Spring就是其中之一,可以完成面向切面编程。然而,AspectJ也实现了AOP的功能,且其实现方式更为简捷,使用更为方便,而且还支持注解式开发。所以,Spring又将AspectJ的对于AOP的实现也引入到了自己的框架中。
        在Spring中使用AOP开发时,一般使用AspectJ的实现方式。
        AspectJ是一个优秀面向切面的框架,它扩展了Java语言,提供了强大的切面实现。
AspectJ中常用的通知有五种类型:前置通知,后置通知,环绕通知,异常通知,最终通知
基于AspectJ的xml配置
下载AOP相关jar:

<dependency> 
	<groupId>org.springframework</groupId> 
	<artifactId>spring-aspects</artifactId> 
	<version>5.2.2.RELEASE</version> 
</dependency>

基于AspectJ的xml配置实现
将装有增强功能的类交由spring管理

 <!--把装有通知的类交给spring管理-->
    <bean id="aop" class="com.ff.spring.aop.AOP"></bean>

    <!--配置切入点和通知-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="save" expression="execution(* com.ff.spring.dao.UserDao.save(..))"/>
        <!--配置通知-->
        <aop:aspect ref="aop">
        <!--方法执行前,
            执行后执行-->
            <!--<aop:before method="doLog" pointcut-ref="save"></aop:before>
                <aop:after method="doLog" pointcut-ref="save"></aop:after>-->
            
            <!--<aop:around method="around" pointcut-ref="save"></aop:around>-->
            <!--异常通知 出现异常后执行-->
            <!--<aop:after-throwing method="throwable" pointcut-ref="save" throwing="e"></aop:after-throwing>-->
            <!--返回通知,执行return后执行-->
            <aop:after-returning method="doLog" pointcut-ref="save"></aop:after-returning>
        </aop:aspect>
    </aop:config>

装有通知的类

public class AOP {
    public void commit(){
        System.out.println("提交事务");
    }

    /*
    通知:连接点上要增强的功能
      通知的时间点:前置通知(方法执行前执行)  后置通知,环绕通知,异常通知,最终通知(return后执行)
     */
    public void doLog(){
        System.out.println("保存日志");

    }

    public void around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("开启事务");
        point.proceed();//调用自己的方法
        System.out.println("提交事务");
    }

    public void throwable(Throwable e){
        System.out.println("出异常啦"+e.getMessage());

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值