spring太强了!两万多字干货 超详细讲解(三)

简介: spring太强了!两万多字干货 超详细讲解

4.3 Spring API接口实现


  • Aop是什么?一般情况下,在程序执行时,是从上到下执行的
  • 如果要在执行的某个点,插入一个功能,如何实现?
  • 比如一个系统,我需要加入逻辑删除,我需要增加日志功能,难道我去修改原有代码?
  • 这就需要我们使用Aop来实现横向切入,增加功能!


我们以增加日志功能为例,介绍Aop的实现流程之一 —— 基于Spring API接口实现


编写一个Service

public interface BookService {
    void add();
    void delete();
    void update();
    void select();
}


编写Service的实现类

public class BookServiceImpl implements BookService {
    public void add() {
        System.out.println("增加了一本书");
    }
    public void delete() {
        System.out.println("删除了一本书");
    }
    public void update() {
        System.out.println("修改了一本书");
    }
    public void select() {
        System.out.println("查询了一本书");
    }
}


编写方法前日志

public class BeforeLog implements MethodBeforeAdvice {
    /**
     * method要执行的目标对象的方法
     * args 参数
     * target 目标对象
     */
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName() + " 的 "+method.getName() + " 被执行了!");
    }
}


编写方法后日志

public class AfterLog implements AfterReturningAdvice {
    /**
     * returnValue  返回对象
     * method要执行的目标对象的方法
     * args 参数
     * target 目标对象
     */
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了 " +method.getName() + " 方法, 返回结果为" + returnValue);
    }
}


配置文件配置切面、切入点

<?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"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id="bookService" class="zwz.demo1.service.BookServiceImpl"/>
    <bean id="beforeLog" class="zwz.demo1.log.BeforeLog"/>
    <bean id="afterLog" class="zwz.demo1.log.AfterLog"/>
    <!--配置AOP-->
    <aop:config>
        <!-- 切入点-->
        <aop:pointcut id="pointcut" expression="execution(* zwz.demo1.service.BookServiceImpl.*(..))"/>
        <!--执行环绕增加 ,将beforeLog切入到pointcut中 -->
        <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>
</beans>


测试

@Test
public void testAop1(){
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    BookService bookService = (BookService) context.getBean("bookService");
    bookService.add();
}

这样,我们就实现了在执行某个方法的时候,输出日志的功能了


输出结果

zwz.demo1.service.BookServiceImpl 的 add 被执行了!
增加了一本书
执行了 add 方法, 返回结果为null
Process finished with exit code 0


4.4 自定义类实现


接下来是基于自定义类接口实现,和spring的API实现一样,先写业务的实现接口和实现类

public interface BookService2 {
    void add();
    void delete();
    void update();
    void select();
}
public class BookServiceImpl2 implements BookService2 {
    public void add() {
        System.out.println("增加了一本书");
    }
    public void delete() {
        System.out.println("删除了一本书");
    }
    public void update() {
        System.out.println("修改了一本书");
    }
    public void select() {
        System.out.println("查询了一本书");
    }
}


和spring API方法一致,编写两个切入日志类

public class BeforeLog implements MethodBeforeAdvice {
    /**
     * method要执行的目标对象的方法
     * args 参数
     * target 目标对象
     */
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName() + " 的 "+method.getName() + " 被执行了!");
    }
}
public class AfterLog implements AfterReturningAdvice {
    /**
     * returnValue  返回对象
     * method要执行的目标对象的方法
     * args 参数
     * target 目标对象
     */
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了 " +method.getName() + " 方法, 返回结果为" + returnValue);
    }
}


编写自定义切入类

public class DiyPointCut {
    public void before(){
        System.out.println("==============方法执行前==============");
    }
    public void after(){
        System.out.println("==============方法执行后==============");
    }
}


配置文件

<bean id="bookService2" class="zwz.demo2.service.BookServiceImpl2"/>
<!--方式二:采用自定义类 配置AOP-->
<bean id="diy" class="zwz.demo2.diy.DiyPointCut"/>
<aop:config>
    <!-- 自定义切面  ref要引用的类-->
    <aop:aspect ref="diy">
        <!-- 切入点-->
        <aop:pointcut id="point" expression="execution(* zwz.demo2.service.BookServiceImpl2.*(..))"/>
        <!-- 通知-->
        <aop:before method="before" pointcut-ref="point"/>
        <aop:after method="after" pointcut-ref="point"/>
    </aop:aspect>
</aop:config>


测试

@Test
    public void testAop2(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookService2 bookService2 = (BookService2) context.getBean("bookService2");
        bookService2.add();
    }
==============方法执行前==============
增加了一本书
==============方法执行后==============


4.5 Java注解实现


和之前两个方法一样,先写Service服务层的接口和实现类

public interface BookService3 {
    void add();
    void delete();
    void update();
    void select();
}
public class BookServiceImpl3 implements BookService3 {
    public void add() {
        System.out.println("增加了一本书");
    }
    public void delete() {
        System.out.println("删除了一本书");
    }
    public void update() {
        System.out.println("修改了一本书");
    }
    public void select() {
        System.out.println("查询了一本书");
    }
}


切面类

@Aspect  //标注这个类是一个切面
public class PointCut {
    @Before("execution(* zwz.demo3.service.BookServiceImpl3.*(..))")
    public void before(){
        System.out.println("==============方法执行前==============");
    }
    @After("execution(* zwz.demo3.service.BookServiceImpl3.*(..))")
    public void after(){
        System.out.println("==============方法执行后==============");
    }
}


配置文件

<!--方式三:采用注解 配置AOP-->
<bean id="bookService3" class="zwz.demo3.service.BookServiceImpl3"/>
<bean id="pointCut" class="zwz.demo3.cut.PointCut"/>
<!--开启注解支持  默认JDK实现(proxy-target-class="false")||  也有cglib-->
<aop:aspectj-autoproxy/>


测试类

@Test
public void testAop3(){
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    BookService3 bookService3 = (BookService3) context.getBean("bookService3");
    bookService3.add();
}


输出结果

==============方法执行前==============
增加了一本书
==============方法执行后==============


五、总结


5.1 总结&附录


spring是一个粘合剂,可以整合其他优秀的框架,大大简化了软件开发的复杂度

我认为spring的核心内容:

  • IOC控制反转
  • AOP面向切面编程

其他内容比如整合mybatis、声明式事务,在后续再写。



5.2 模板文件


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


mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <package name="zwz.pojo"/>
    </typeAliases>
    <environments default="zwz">
        <environment id="zwz">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper class="zwz.mapper.UserMybatisMapper"></mapper>
    </mappers>
</configuration>


5.3 spring配置标签


bean

bean用来注册实体类,可以注入相应的变量值

<bean id="user" class="zwz.pojo.User">
    <property name="name" value="ZWZ"/>
    <property name="age" value="18"/>
</bean>


alias


设置别名,设置后原名和别名都可以使用

bean 中的 name 属性也可以做别名,而且功能更加强大

<bean id="user" class="zwz.pojo.User">
    <property name="name" value="ZWZ"/>
    <property name="age" value="18"/>
</bean>
<alias name="user" alias="userZwz"/>

可以在测试类中这样调用别名bean

// ApplicationContext Spring上下文对象 | ClassPathXmlApplicationContext 从配置文件中去取
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 从容器中取出user对象
User user = (User) context.getBean("userZwz");


import

在团队开发中,每个人都需要拥有自己的配置文件,可以通过import标签将多个配置文件整合成一个

如张三的配置文件 —— bean1.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
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="user" class="zwz.pojo.User">
        <!-- property相当于给某个变量设置一个值-->
        <property name="name" value="ZWZ"/>
        <property name="age" value="18"/>
    </bean>
    <alias name="user" alias="userZwz"/>
</beans>

团队整体的配置文件 —— applicationContext.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
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    <import resource="bean1.xml"/>
</beans>


context

自动装配bean

<context:annotation-config/>

扫描指定包的组件

<!--指定要扫描的包 这个包下的注解就会生效-->
<context:component-scan base-package="zwz"/>
相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
安全 Java 测试技术
Github标星98k,Alibaba最新发布的Spring Boot项目实战文档!太强了
前言 又到了一年一度的备战秋招的时间,虽然这两年因为经济环境不太好,互联网行业的各大厂都再裁员,但是今年的秋招经济形势正在复苏,我特地拜托阿里的朋友将这份Spring Boot项目实战开发文档分享出来。 本文档涵盖Spring Boot企业级项目开发的各方面知识,重点介绍Maven项目的搭建、Jersey Restful风格、Postman测试接口、Swagger2可视化文档、Lombok优雅编码、Redis缓存、Security安全机制、Web Service服务、WebSocke t通信、性能测试、集成测试、Jeecg Boot快速开发框架、使用Docker进行项目部署、使
|
安全 Java 测试技术
Github标星98k,Alibaba最新发布的Spring Boot项目实战文档!太强了
前言 又到了一年一度的备战秋招的时间,虽然这两年因为经济环境不太好,互联网行业的各大厂都再裁员,但是今年的秋招经济形势正在复苏,我特地拜托阿里的朋友将这份Spring Boot项目实战开发文档分享出来。 本文档涵盖Spring Boot企业级项目开发的各方面知识,重点介绍Maven项目的搭建、Jersey Restful风格、Postman测试接口、Swagger2可视化文档、Lombok优雅编码、Redis缓存、Security安全机制、Web Service服务、WebSocke t通信、性能测试、集成测试、Jeecg Boot快速开发框架、使用Docker进行项目部署、使用sp
440 0
|
XML Java 数据格式
spring太强了!两万多字干货 超详细讲解(二)
spring太强了!两万多字干货 超详细讲解
184 0
|
XML Java Maven
spring太强了!两万多字干货 超详细讲解(一)
spring太强了!两万多字干货 超详细讲解
313 0
|
消息中间件 分布式计算 数据可视化
Spring Boot + 规则引擎 URule,太强了!
Spring Boot + 规则引擎 URule,太强了!
|
Java Docker 容器
Docker + Spring Boot + FastDFS 搭建一套分布式文件服务器,太强了
首先说一下从零开始自己去搭一个fastdfs挺麻烦,后来看到有人把做好的 docker 镜像传出来了,那搭建起来就很容易了
398 0
Docker + Spring Boot + FastDFS 搭建一套分布式文件服务器,太强了
|
12月前
|
Java Spring 容器
SpringBoot自动配置的原理是什么?
Spring Boot自动配置核心在于@EnableAutoConfiguration注解,它通过@Import导入配置选择器,加载META-INF/spring.factories中定义的自动配置类。这些类根据@Conditional系列注解判断是否生效。但Spring Boot 3.0后已弃用spring.factories,改用新格式的.imports文件进行配置。
1424 0
|
人工智能 Java 测试技术
Spring Boot 集成 JUnit 单元测试
本文介绍了在Spring Boot中使用JUnit 5进行单元测试的常用方法与技巧,包括添加依赖、编写测试类、使用@SpringBootTest参数、自动装配测试模块(如JSON、MVC、WebFlux、JDBC等),以及@MockBean和@SpyBean的应用。内容实用,适合Java开发者参考学习。
1330 0
|
前端开发 Java 数据库
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——Thymeleaf 介绍
本课介绍Spring Boot集成Thymeleaf模板引擎。Thymeleaf是一款现代服务器端Java模板引擎,支持Web和独立环境,可实现自然模板开发,便于团队协作。与传统JSP不同,Thymeleaf模板可以直接在浏览器中打开,方便前端人员查看静态原型。通过在HTML标签中添加扩展属性(如`th:text`),Thymeleaf能够在服务运行时动态替换内容,展示数据库中的数据,同时兼容静态页面展示,为开发带来灵活性和便利性。
584 0
|
9月前
|
JavaScript Java Maven
【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!
SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础
638 4