一篇搞定Spring,IOC容器,Bean管理,3.AOP底层原理和实现(收下吧,真的很详细)

1.Spring容器的概念

Spring是一个轻量级的框架,可以解决企业开发的复杂性,让开发效率提升,他核心的两个点是:

1.IOC

IOC:在java中,我们程序员一般是去创建一个对象,那么有个问题就是耦合性太高了,在后期的修改和维护的维修成本比较大,在IOC中,对象的创建依赖注入是由容器负责,而不是由程序员直接控制,他是通过dl的注入方式,来实现对象直接的解耦,提高了代码的灵活性和可维护性

2.AOP

AOP:AOP也被称为面向切面,他可以在不改变原代码对功能进行增强

1.2,Spring入门

首先我们要在pom.xml中添加spring的依赖

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.24</version>
        </dependency>


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

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
<!--            <scope>test</scope>-->
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.23</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>



    </dependencies>

在这里我添加了mysql的依赖,大家也可以先添加上去,在后面我们的案例中会用到,如果下载失败或者网络原因下载中断,或者还不会配置maven的可以参考我之前写的

https://blog.csdn.net/m0_70812512/article/details/139581648?spm=1001.2014.3001.5502

在这里就会有你spring的依赖项

如果说你去创建xml没有这个图标说明你spring依赖没有配置好。

好接下来我们通过几个案例来了解到这个spring注入的方式

1.通过xml实现注入

通过我们去拿取这个对象中的方法时都是去创建他,这个会很繁琐,而且后期维护性也不高

那么我们就可以通过spring将对象交给spring去管理,让spring帮我们去注入

1.set注入

首先看这里,在这里我们创建了一个user类,在这个类中我修饰了一个name,并且为这个name提供了一个set方法,用于注入值,并且提供了一个构造函数,那么他现在是符合springbean注入的条件

现在我通过xml来注入,我们定义了一个bean的标签,并且指定了他所以管理的对象是User,在property中我们指定了User中的属性名name,并且为name赋值

现在我们来测试看看会是什么结果

//        加载自定义的spring配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("beans2.xml");
// 获取配置文件对象User
        User user = context.getBean("user",User.class);
// 操作user对象
//        System.out.println(user);
        user.add();

在这里我们可以看到,我们告诉了spring是那一个配置文件,那他就会根据你配置文件中所定义的bean去构造这个对象,在通过getbean获取到这个对象(我们给每个bean都设置了id),并且调用其中的方法,这样就不在是我们程序员手动创建对象了,而是交给spring管理,让他帮我们来管理这个对象

<!--    属性注入方式-->
    <bean id="user2" class="com.zking.Utile.User">
        <property name="name" value="谭建涛"></property>
    </bean>

    <!--    构造注入方式-->
    <bean id="user3" class="com.zking.Utile.User">
        <constructor-arg name="name" value="有参构造注入方式"></constructor-arg>
    </bean>

    <!--    p注入方式-->
    <bean id="user4" class="com.zking.Utile.User"  p:name="p注入方式">

    </bean>

当然这里还有一些其他的注入方式大家也可以去试试,在这里我们就不全部展示出来了,他们的意思都一样,就是通过springIOC来管理这个创建对象的过程,我们去拿就行

接下来我们来按照我们经常写代码的一些主要配置来搞几个小案例

 我们看这里,我有一个数据访问层和一个业务逻辑层,在业务逻辑层中构造了数据访问层的这个对象,并且里面提供了一个

User_Sevsiver

方法,在这个方中可以去直接实现我们UserDao中的执行语句

好,现在我们来看xml,我将Userdao和UserServer都交给spring管理,并且设置了一个不同的id

在UserServier中就会去注入这个UserDao(上面id是UserDao),那既然我们已经注入了UserDao在这个set方法中了,那我在去调UserServier中的

User_Sevsiver

方法,他不就是会去执行到UserDao中的方法吗

实现了吧,是吧,其他案例我就不一一写了,基本都都大差不差,其实就是原来我们要直接去创建对象,现在不用了,给spring去管理,我们拿就好了,spring通过dl注入实现IOC控制反转

在说一个吧,spring自动装配

在这里我们将UserDao和UserSever交给spring管理,并且在 后面我们添加了autowire="byName",这个的意思是springIOC中的一个自动装配的一方式,他会扫描ImpUserServer中的属性值,比如说是userdao,那么他就会尝试将userdao注入到usersever这个bean当中,就可以实现spring的自动装配

1.3.通过组件扫描的方式实现

虽然说这种xml声明的方式确实可以实现我们的IOC控制反转,但是这个步骤什么的到处配置还是会有点麻烦,那么spring肯定还有其他的方式来实现这个控制反转,那就是组件扫描

1.什么是组件扫描

我们来看这个张图,我们原来是不是声明告诉spring,我指定那些要注入的东西那我们在根据他这个id去调这个bean,就可以实现这个方法了吧。

那有没有一种方式就是说,我可以给每一个对象中去声明一个标识符,在让spring通过标识符来识别变成一个bean,并且扫描不是指定某一个类来实现,而是去扫描结构下的所以类,当然有,我们来看上面的图片,我们指定开起了组件扫描,扫描com.zking下面的所以类

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

    <!--    开启组件扫描,当前扫描com.zking下的全部组件-->
    <!--    <context:component-scan base-package="com.zking"></context:component-scan>-->
    <!--    是 Spring 的注解驱动配置之一,用于自动扫描指定包下的组件,-->
    <!--    如带有 @Component, @Repository, @Service, @Controller 等注解的类,并将其注册为 Spring 的 Bean。-->

    <context:component-scan base-package="com.zking"></context:component-scan>



</beans>

这里的

 @Component, @Repository, @Service, @Controller 

就是我们今天要说的通过注解的方式实现DL注入

首先我们先来了解这是是什么,首先要知道spring就是通过识别出com.zking下面的所以包含这些注解的来作为spring的bean,那有了这个bean,他就可以通过这个bean去里面拿这个对象去实现这个方法。

@Component:是spring当中的一个注解,他一般是拥有业务逻辑层,你可以理解为他将自己变成了一个spring可以扫描识别到变成一个bean

@Repository:一般用于数据访问层,他就是告诉spring我这个类是用于数据访问的

@Service:一看名字就知道了吧,他其实就是告诉spring他是业务逻辑层

@Controller:这个注解标记的类是一个 Spring MVC 控制器组件,用于处理 HTTP 请求和响应。它扩展了 @Component 注解,通常与 Spring MVC 框架结合使用,用于构建 Web 应用。

他们都可以和@Autowired 或 @Resource 等注解来自动装配 Bean

@Autowired:是spring的自动注解,我们声明的全局变量中

在这里我们创建了一个ImpUser_Dao类,并且将他标记为
@Repository("userDao")spring中的组件,这里这个的意思是为相当于注入对象的name属性,可以理解为id,默认是这个类小写,impUser_Dao,那么在 ImpUserSever_Dao 中,我们设置为自动注入@Autowired,在UserDao userDao = null;userdao要和你那个dao里面的@Repository("userDao")值一致,因为他是通过你这个name的属性值在com.zking下去扫描,去找,找到了就将这个对象注入进去,在最后我们就可以通过
UserSever serv = apl.getBean("impUserSever_Dao",UserSever.class);

去创建这个类并且调用他里面的方法(默认是首字母小写),那么他就会自动的将Userdao注入进去,我们在调里面的方法是也就可以执行到数据访问逻辑层中了

那么这种其实还是依赖了xml,如果不想依赖xml,完全注解开发

package com.zking.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

//标记当前类为配置类
@Configuration
// 开启组件扫描
@ComponentScan({"com.zking"})
//引入外部配置文件
@PropertySource("db.properties")
public class SpringUserConfig {
}

我们可以通过创建一个java类,在类中将他声明为他是配置文件

在通过 

ApplicationContext apl = new AnnotationConfigApplicationContext(SpringUserConfig.class);

作引入,是相同的效果。

3.AOP底层原理和实现

1.AOP是什么

简单来说aop就说在不改变原代码时,对原来的功能增强

AOP也被称为面向切面,切面的意思是为他是由我们定义的切点组成的,可以理解为我现在有两个类,一个userdao,一个Studentdao,他们下面分别有add,update方法,那么他们类里面的方法又可以叫切点,那么我们就可以定义这个切点为一个切面,对我们的功能代码增强。 

2.AOP的底层原理

 就是动态代理,动态代理又可以分为

有接口的情况:JDK动态代理

无接口情况:CGLIB动态代理

1.有接口的情况:JDK动态代理

package com.zking.dao.imp;

import com.zking.dao.UserDao;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;

@Repository
public class ImpUserDao implements UserDao {

    @Override


    public void add() {
        System.out.println("数据添加");
    }

    @Override
    public void Update() {
        System.out.println("数据修改");
    }
}

创建Userdao接口代理对象

 2.无接口情况:CGLIB动态代理

package com.zking.proxy.CGilb;

public class User {
    public void add(){
        System.out.println("CGLIB方式");
    }
    public static class person extends User{
        public void add(){
            System.out.println("CGLIB开启事务");
            super.add();
            System.out.println("CGLIB事务提交");
        }
    }

}

没有接口,而是直接继承这个类中的方法在方法之前作增强

java动态代理

package com.zking.proxy;

import com.zking.dao.UserDao;

/**
 * 用户Dao代理类,用于在不修改原有UserDao实现的基础上,添加额外的功能(如日志、事务等)。
 */
public class UserDaoproxy2 {

    private UserDao userDao;

    /**
     * 构造函数,传入UserDao实例,代理类将围绕这个实例进行操作。
     * 
     * @param userDao 需要被代理的UserDao实例
     */
    public UserDaoproxy2(UserDao userdao) {
        this.userDao = userdao;
    }

    /**
     * 创建UserDao的代理实例。
     * 
     * @return 返回代理后的UserDao实例
     */
    public UserDao newProxyInstance() {
        System.out.println("代理类");
        // 使用Java反射机制创建代理实例,代理实现类为UserInvoaction
        return (UserDao) java.lang.reflect.Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), new UserInvoaction());
    }

    /**
     * InvocationHandler实现类,用于处理代理对象的方法调用。
     */
    class UserInvoaction implements java.lang.reflect.InvocationHandler {
        /**
         * 当调用代理对象的方法时,实际上会执行此方法。
         * 
         * @param proxy 代理对象
         * @param method 被调用的方法
         * @param args 方法参数
         * @return 方法返回值
         * @throws Throwable 方法执行中抛出的异常
         */
        public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws Throwable {
            System.out.println("前置增强");
            // 调用原始UserDao实例的方法
            Object obj = method.invoke(userDao, args);
            System.out.println("后置增强");
            // 返回方法执行结果
            return obj;
        }
    }
}

4.AOP准备工作

Aspectl介绍

在spring当中一般都在基于Aspectl实现aop操作的,Aspectl不是spring的一部分,而且是一个独立的AOP框架,一般把Aspectl和Spring一起使用,进行AOP操作,因为这样更方便

基于Aspectl进行AOP 操作的方式有两种

1.基于xml配置文件的方式实现

2.基于注解的方式实现

基于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: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
        ">

    <!--    开启组件扫描,当前扫描com.zking下的全部组件-->
    <!--    <context:component-scan base-package="com.zking"></context:component-scan>-->
    <!--    是 Spring 的注解驱动配置之一,用于自动扫描指定包下的组件,-->
    <!--    如带有 @Component, @Repository, @Service, @Controller 等注解的类,并将其注册为 Spring 的 Bean。-->

    <context:component-scan base-package="com.zking"></context:component-scan>
<!--    <context:component-scan base-package="com.zking">-->
<!--        <context:exclude-filter type="assignable" expression="com.zking.aop.LogAspect"/>-->
<!--    </context:component-scan>-->

<!--    开启aspectl生成代理对象-->
<!--    roxy-target-class="true"代理目标可以是类,默认为接口-->
    <aop:aspectj-autoproxy/>

</beans>

首先我们在xml中开启组件扫描,扫描com.zking下面的所以类,并且开启aspectl生成代理对象

 

现在我有一个UserServerImp的类,类中有这些方法

package com.zking.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.management.DescriptorKey;

//@Aspect : 表明当前类是增强类
@Aspect
@Order(1)
@Component
public class LogAspect {
//    设置切点
//@Pointcut("execution(* com.zking.dao..*.*(..))")
@Pointcut("execution(* com.zking..*.*(..))")
public void pointcut(){

}

    @Before("pointcut()")

    public void before() {
        System.out.println("UserSeverimp前置通知");
    }
    @After("pointcut()")
    public void after(){
        System.out.println("UserSeverimp后置通知");
    }
    @AfterReturning("pointcut()")
    public void afterReturning(){
        System.out.println("UserSeverimp返回通知");
    }
    @AfterThrowing("pointcut()")
    public void afterThrowing(){
        System.out.println("UserSeverimp异常通知");
    }
    @Around("pointcut()")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable{
//        System.out.println("UserSeverimp环绕通知");
        joinPoint.proceed();
        System.out.println("UserSeverimp环绕通知");
    }

}

并且又创建了一个类,@Aspect : 表明当前类是增强类,

@Pointcut("execution(* com.zking..*.*(..))")

这个帮忙当前com.zking下面所以类中所以的方法,属性为任意类型,这样就组成了一个切面,切面下面有各种各样方方法,那么在执行程序时就会去扫描,看那些增强类,然后对类实现增强功能,

 

可以看到,本来我应该只是会输出用户添加的,但是因为我们配置了AOP,他就会在我们代码执行之前先执行我们增强类中的方法。好了,今天就到这里啦,累了兄弟们。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/718295.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Windows采用txt和bat来一次性建立多个文件夹

前言 最近工作需要一次性建立多个文件夹&#xff0c;方便保存不同的数据&#xff0c;所以在网上搜了搜方法&#xff0c;方法还挺多的&#xff0c;这里只是给出流程最简洁、最适合自己的方法&#xff0c;供自己日后回顾&#xff0c;如果大家想学习更多方法可以百度一下。 方法…

Hue Hadoop 图形化用户界面 BYD

软件简介 Hue 是运营和开发 Hadoop 应用的图形化用户界面。Hue 程序被整合到一个类似桌面的环境&#xff0c;以 web 程序的形式发布&#xff0c;对于单独的用户来说不需要额外的安装。

白酒:茅台镇白酒的品牌合作与跨界营销案例

云仓酒庄豪迈白酒&#xff0c;作为茅台镇的知名品牌&#xff0c;在品牌合作与跨界营销方面也有着杰出的表现。通过与不同领域品牌的合作&#xff0c;豪迈白酒进一步拓宽了市场渠道&#xff0c;提升了品牌曝光度和影响力。 首先&#xff0c;云仓酒庄豪迈白酒与品质餐产品牌的合作…

【SpringCloud学习笔记】RabbitMQ(中)

1. 交换机概述 前面《RabbitMQ上篇》我们使用SpringAMQP来演示如何用Java代码操作RabbitMQ&#xff0c;当时采用的是生产者直接将消息发布给队列&#xff0c;但是实际开发中不建议这么做&#xff0c;更加推荐生产者将消息发布到交换机(exchange)&#xff0c;然后由exchange路由…

Mac M3 Pro 部署Flink-1.16.3

目录 1、下载安装包 2、解压及配置 3、启动&测试 4、测试FlinkSQL读取hive数据 以上是mac硬件配置 1、下载安装包 官网&#xff1a;Downloads | Apache Flink 网盘&#xff1a; Flink 安装包 https://pan.baidu.com/s/1IN62_T5JUrnYUycYMwsQqQ?pwdgk4e Flink 已…

✅生产问题之Emoji表情如何操作存储,MySQL是否支持

针对 Emoji 表情 MySQL 存储是否支持的问题&#xff0c;结论是&#xff1a; MySQL 中可以存储 emoji 表情&#xff0c;但需要使用 UTF8MB4 字符编码。如果使用 UTF8MB3&#xff0c;存储这些扩展字符会导致解析错误。 课外补充 MySQL 对 Unicode 的支持 Unicode 字符集已成为…

win环境安装Node.js的多种方式

今天我们分享win环境安装Node.js的多种方式&#xff1a; 首先要明白Node.js是一个JavaScript运行环境&#xff0c;它基于Google的V8引擎进行封装&#xff0c;允许JavaScript运行在服务器端。Node.js让JavaScript成为一种与PHP、Python、Perl、Ruby等服务端语言平起平坐的脚本语…

聊聊redis中的字典的实现

写在文章开头 redis作为非关系数据库&#xff0c;其底层采用了字典(也称为映射)保存键值对。本文会基于源码分析的方式带你了解redis中这一常见数据结构的精巧设计&#xff0c;希望对你有帮助。 Hi&#xff0c;我是 sharkChili &#xff0c;是个不断在硬核技术上作死的 java c…

Spring Security——添加验证码

目录 项目总结 新建一个SpringBoot项目 VerifyCode&#xff08;生成验证码的工具类&#xff09; WebSecurityController控制器 VerifyCodeFilter&#xff08;自定义过滤器&#xff09; WebSecurityConfig配置类 login.html登录页面 项目测试 本项目是以上一篇文章的项目…

DC/AC电源模块:提升光伏发电系统的能源利用率

BOSHIDA DC/AC电源模块&#xff1a;提升光伏发电系统的能源利用率 随着环境保护意识的提高和能源需求的增加&#xff0c;光伏发电系统作为一种清洁能源的代表&#xff0c;受到了越来越多的关注。然而&#xff0c;光伏发电系统在实际应用中还存在一些问题&#xff0c;如发电效率…

【UIDynamic-动力学-UICollisionBehavior-碰撞模式-创建边界 Objective-C语言】

一、我们来说这个碰撞模式 1.把之前的代码备份一下,改个名字:“04-碰撞行为-碰撞模式”, 然后,command + R,先跑一下, 我现在,一点击,是这个红色的View、和蓝色的View、在发生碰撞, 我们说,碰撞模式是啥意思, collision里边,有一个叫做collisionMode, UICollis…

Camtasia Studio 2024软件下载附加详细安装教程

amtasia Studio 2024是一款功能强大的屏幕录制和视频编辑软件&#xff0c;由TechSmith公司开发。这款软件不仅能够帮助用户轻松地记录电脑屏幕上的任何操作&#xff0c;还可以将录制的视频进行专业的编辑和制作&#xff0c;最终输出高质量的视频教程、演示文稿、培训课程等。 …

geoserver 如何设置数据目录

在GeoServer中&#xff0c;数据目录是存储配置文件、数据存储、图层、样式等的重要目录。默认情况下&#xff0c;GeoServer的数据目录位于GeoServer安装目录下的data_dir文件夹。但在很多情况下&#xff0c;用户可能希望将数据目录设置在一个自定义位置&#xff0c;以便更好地管…

独立游戏之路:Tap篇 -- Unity 集成 TapTap 广告详细步骤

Unity 集成 TapADN 广告详细步骤 前言一、TapTap 广告介绍二、集成 TapTap 广告的步骤2.1 进入广告后台2.2 创建广告计划2.3 选择广告类型三、代码集成3.1 下载SDK3.2 工程配置3.3 源码分享四、常见问题4.1 有展现量没有预估收益 /eCPM 波动大?4.2 新建正式媒体找不到预约游戏…

公共服务数字化转型的五个路径

数字化技术赋能公共服务&#xff0c;主要以数据为着力点&#xff0c;通过数据驱动优化或重塑公共服务架构。基于用数据决策、用数据服务、用数据创新的现代化的公共服务供给模式&#xff0c;推进“信息数字化业务数字化组织业务化”的全方位公共服务数字化&#xff0c;进而赋能…

深入学习html的步骤

推荐的学习步骤&#xff1a; 1. 深入了解HTML基础标签 列表 HTML提供有序列表(<ol>)和无序列表(<ul>)。 <h2>无序列表</h2> <ul><li>项目一</li><li>项目二</li><li>项目三</li> </ul><h2>…

Vue48-ref属性

一、需求&#xff1a;操作DOM元素 1-1、使用原生的id属性 不太好&#xff01; 1-2、使用 ref属性 原生HTML中&#xff0c;用id属性给元素打标识&#xff0c;vue里面用ref属性。 给哪个元素加了ref属性&#xff0c;vc实例对象就收集哪个元素&#xff01;&#xff01;&#xff0…

【Oracle生产运维】数据库服务器高负载排查处理

说明 在Oracle数据库运维工作中&#xff0c;经常会遇到Oracle数据库服务器平均负载&#xff08;load average&#xff09;突然异常升高&#xff0c;如果放任不管&#xff0c;严重的情况下会出现数据库宕机、服务器重启等重大故障。因此&#xff0c;当发现数据库服务器平均负载…

房间预订系统怎么做

在这个日新月异的时代&#xff0c;旅游已经成为了许多人生活中不可或缺的一部分。然而&#xff0c;在规划一场完美的旅行时&#xff0c;房间预订往往是一个让人头疼的问题。今天&#xff0c;我要为大家揭秘一款颠覆传统的房间预订系统——它不仅仅是一个预订工具&#xff0c;更…

需求虽小但是问题很多,浅谈JavaScript导出excel文件

最近我在进行一些前端小开发&#xff0c;遇到了一个小需求&#xff1a;我想要将数据导出到 Excel 文件&#xff0c;并希望能够封装成一个函数来实现。这个函数需要接收一个二维数组作为参数&#xff0c;数组的第一行是表头。在导出的过程中&#xff0c;要能够确保避免出现中文乱…