Spring两大核心IOC、AOP

本文介绍了Spring框架的两大核心——IOC(控制反转)和AOP(面向切面编程),阐述了它们的概念和作用。通过IOC,Spring管理对象的生命周期和依赖关系,降低了系统耦合度。AOP则提供了在不修改原有代码的情况下,实现功能扩展的能力,常用于日志记录、事务管理等。文中还提及了bean标签的使用以及Spring在实际项目中的应用。

Spring两大核心IOC、AOP

简介

​ Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架,以IOC(Inverse Of Control:反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层 Spring MVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的 Java EE 企业应用开源框架。

优点

方便解耦,简化开发:通过 Spring 提供的 IOC 容器,可以将对象间的依赖关系交由 Spring 进行控制,避免硬编码所造成的过度程序耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。

AOP 编程的支持:通过 Spring 的 AOP 功能,方便进行面向切面的编程,许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松应付。

声明式事务的支持:可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务的管理,提高开发效率和质量。

方便程序的测试:可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情。

方便集成各种优秀框架:Spring 可以降低各种框架的使用难度,提供了对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的直接支持。

降低 JavaEE API 的使用难度:Spring 对 JavaEE API(如 JDBC、JavaMail、远程调用等)进行了薄薄的封装层,使这些 API 使用难度大为降低。

Java 源码是经典学习范例:Spring 的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对 Java 设计模式灵活运用以及对 Java 技术的高深造诣。它的源代码无意是 Java 技术的最佳实践的范例。

IOC

在采用面向对象方法设计的软件系统中,底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑。即软件系统中对象之间的耦合,对象A和对象B之间有关联,对象B又和对象C有依赖关系,这样对象和对象之间有着复杂的依赖关系。而IOC让复杂系统分解成相互合作的对象,这些对象类通过封装以后,内部实现对外部是透明的,从而降低了解决问题的复杂度,而且可以灵活地被重用和扩展。其原理是基于面向对象(OO)设计原则的The Hollywood Principle:Don’t call us, we’ll call you(别找我,我会来找你的)。也就是说,所有的组件都是被动的,所有的组件初始化和调用都由容器负责。组件处在一个容器当中,由容器负责管理。

简单的来讲,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控,即在一个类中调用另外一个类。这也就是所谓“控制反转”的概念所在:控制权由应用代码中转到了外部容器,控制权的转移,即所谓反转。在Spring IOC中经常用到一个设计模式,即工厂模式。工厂模式提供创建对象的接口。

IOC容器就类似于工厂模式中生产对象的工厂类Factory,工厂类根据传递进来的类名,通过Java反射技术,动态生成相应的具体对象。在spring中,IOC容器用配置文件来定义,使得工厂和对象生成这两者独立分隔开来。

bean标签

使用Spring来创建对象,在spring这些都称为Bean
bean = 对象  new Hello();
id = 变量名
class = new 的对象

bean 标签 :用于配置让 spring 创建对象,并且存入 ioc 容器之中

id 属性 :对象的唯一标识。

class 属性 :指定要创建对象的全限定类

从容器中获取 对象方法:

ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");

User u = (User) context.getBean("User");

System.out.println(u);

ApplicationContext :接口的实现类

ClassPathXmlApplicationContext:它是从类的根路径下加载配置文件 推荐使用这种

FileSystemXmlApplicationContext:它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。

AnnotationConfigApplicationContext:当我们使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。

AOP

AOP能够让我们在不影响原有功能的前提下,为软件横向扩展功能。那么横向扩展怎么理解呢,我们在WEB项目开发中,通常都遵守三层原则,包括控制层(Controller)->业务层(Service)->数据层(dao),那么从这个结构下来的为纵向,它具体的某一层就是我们所说的横向。实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。我们的AOP就是可以作用于这某一个横向模块当中的所有方法。

Joinpoint(连接点) :所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的连接点。

Pointcut(切入点): 所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义。

Advice(通知/增强): 所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。

Introduction(引介): 引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类动态地添加一些方法或 Field。

Target(目标对象): 代理的目标对象。

Weaving(织入) : 是指把增强应用到目标对象来创建新的代理对象的过程。spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。

Proxy(代理) :一个类被 AOP 织入增强后,就产生一个结果代理类。

Aspect(切面) :是切入点和通知(引介)的结合。

在这里插入图片描述

bean.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" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <aop:aspectj-autoproxy/>
<!--    注解功能-->
    <context:annotation-config/>
<!--    扫描包-->
    <context:component-scan base-package="com.spongebob"/>

</beans>

dao层

public interface ICustomerDao {
    // 这里定义,对客户表所做的所有操作 insert update delete
    public void insert();
    public  void select();

}
@Repository("dao")
public class CustomerDao implements ICustomerDao {

    public void insert(){
        System.out.println("CustomerDao.insert()");
    }
    
    public  void select(){
        System.out.println("CustomerDao.select()");
    }
}

业务层

@Service  //表示是一个业务逻辑处理对象 完成的功能和 component 一样
public class CustomerBiz {

    private ICustomerDao dao;

    public ICustomerDao getDao() {
        return dao;
    }

    @Autowired  //自动注入
    public void setDao(ICustomerDao dao) {
        this.dao = dao;
    }
    
    //dosomething
    public void reg(){
        dao.insert();
        dao.select();
    }
  
}

切入方法

@Aspect
@Component("myAspect")
public class MyAspect {

    //在getDao调用前、后切入通知
    @Before("execution(* com.spongebob.biz.CustomerBiz.getDao(..))")
    public void beforeBizGetDao(){
        System.out.println("getDao=====前置通知");
    }
    
    @AfterReturning("execution(* com.spongebob.biz.CustomerBiz.getDao(..))")
    public void methodBizGetDao(){
        System.out.println("getDao=====后置通知");
    }

    
    //对insert()方法前后切入通知
    @Before("execution(* com.spongebob.mapper.ICustomerDao.insert(..))")
    public void insertBefore(){
        System.out.println("insert=====前置通知");
    }
    
   @AfterReturning("execution(*com.spongebob.mapper.ICustomerDao.insert(..))")
    public void insertAfter(){
        System.out.println("insert=====后置通知");
    }

    //对select进行环绕通知
    @Around("execution(* com.spongebob.mapper.ICustomerDao.select(..))")
    public void insertAround(){

        System.out.println("select==环绕通知==");
    }
    
}

测试类

public class App {
    public static void main( String[] args ) {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");

        CustomerBiz biz = context.getBean("customerBiz", CustomerBiz.class);

        biz.getDao().insert();
        biz.getDao().select();
    }
}

运行结果

Constuctor 
getDao=====前置通知
getDao=====后置通知
insert=====前置通知
CustomerDao.insert()
insert=====后置通知
getDao=====前置通知
getDao=====后置通知
select==环绕通知==
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值