Spring简单总结

SpringFarmwork

一、什么是IOC
首先要认识到IOC是一种思想,简单来说,就是将我们的手中的控制权转交出去,就像是玩斗地主时候的托管。
在SpringFarmwork中,主要的表现就是,我们将我们手中的创建对象的权利转交了出去,我们需要对象的时候只需要向计算机去讨要就行了。
二、什么是DI
DI有可以叫做依赖注入,DI是IOC的一种实现方式。在SpringFarmwork中我们最主的方式有通过Set方式注入和通过Constructor方式注入。通俗的说就是给我们创建的对象的属性赋值,可以通过对象的Set方法和构造器来实现。
有了这两个概念以后,我们就可以来尝试简单使用一下SpringFarmwork。
三、简单使用SpringFarmwork
首先我们创立一个简单的Maven项目,导入相关的jar包
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<!--导入这一个jar包其他相关的也会跟着导入进来-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.14</version>
</dependency>

之后我们来写Spring的配置文件,把它放在resources文件夹下

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



</beans>

假如说我们有一个简单的实体类User(实现了Get和Set方法,重写了toString())

package com.nbu.pojo;

public class User {
    private String username;
    private String password;

    public User() {
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

我们现在来尝试着来注入一下它

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

		<!--这里是通过Set方法注入的-->
    <bean id="user" class="com.nbu.pojo.User">
        <property name="username" value="root"/>
        <property name="password" value="123456789"/>
    </bean>

</beans>

这样其实就算是注入完毕了,其中这个对象的username属性值为root,password属性值为123456789,接下来我们尝试着去获取这个对象。

package com.nbu;

import com.nbu.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
    //这里是先去把我们前面配置的xml文件注册
       ApplicationContext Context =new  ClassPathXmlApplicationContext("springDao.xml");
       //通过上下文来获取我们前面在xml文件里写入的user
       User user = Context.getBean("user",User.class);
       //打印这个user的内容
       System.out.println(user);
    }
}

运行的结果如下
在这里插入图片描述

这里我们可以看到结果是正确的,我们接下来尝试着使用一下构造器来完成属性注入,不过这样的话,我们就需要来修改一下我们的User类了,因为我们之前的User类里是无参构造函数。
User类修改完毕后如下

package com.nbu.pojo;

public class User {
    private String username;
    private String password;

    public User() {
    }

    public User(String username,String password) {
        this.username = username;
        this.password = password;
    }



    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

我们修改一下我们之前的Spring的配置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
  https://www.springframework.org/schema/beans/spring-beans.xsd">
		<!--通过构造器注入的方法有三种这里是比较舒服的一种-->
		<!--下面三种在配置文件里放任意一个就行了不然会报错-->
		<!--这里我们是通过构造器的参数的参数名来实现的属性注入-->
    <bean id="user" class="com.nbu.pojo.User">
        <constructor-arg name="username" value="root"/>
        <constructor-arg name="password" value="123456789"/>
    </bean>
		<!--第二种方法我们来尝试通过参数的下标来完成属性注入-->
		<bean id="user" class="com.nbu.pojo.User">
        <constructor-arg index="0" value="root"/>
        <constructor-arg index="1" value="123456789"/>
    </bean>
    <!--第三种方式是通过构造器中的参数的数据类型来完成属性注入-->
    <!--虽然这里两个都是String所以是按顺序完成了属性的注入-->
    <bean id="user" class="com.nbu.pojo.User">
        <constructor-arg type="java.lang.String" value="root"/>
        <constructor-arg type="java.lang.String" value="123456789"/>
    </bean>
</beans>

运行的结果如下
在这里插入图片描述
实际如果只是使用就是这么的简单,没有多么的复杂,整个SpringFarmwork就一个IOC和一个AOP就没了,重要的是将他和其他的框架整合在一起(后面我会介绍将他和Mybatis整合在一起使用)

让我们接着往下看,我们现在来一起看自动注入这个是比较重要的。

四、自动注入
所谓spring自动注入,是指容器中的一个组件中需要用到另一个组件(例如聚合关系)时,依靠spring容器创建对象,而不是手动创建。(ps:这句话引用自https://www.cnblogs.com/dubhlinn/p/10708142.html)。
由于我们之前的目录结构里,没有这中聚合关系,所以我们这里新建两个实体类Student和Address
package com.nbu.pojo;

public class Student {
    private String name;
    private Address address;

    public String getName() {
        return name;
    }

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

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address adress) {
        this.address = adress;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", " + address.toString() +
                '}';
    }
}
package com.nbu.pojo;

public class Address {
    private String country;
    private String province;

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    @Override
    public String toString() {
        return "Address={" +
                "country='" + country + '\'' +
                ", province='" + province + '\'' +
                '}';
    }
}

我们现在来使用第一种方式byName注入,就是我们这里可以通过Student当中Address的属性名和已经注册了的Bean相匹配来完成注册,如下

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

    <bean id="address" class="com.nbu.pojo.Address">
        <property name="country" value="中国"/>
        <property name="province" value="福建省"/>
    </bean>

		<!--我这里并没有去收动的去配置属性addres-->
		<!--如果要手动配置的话如下
	<bean id="student" class="com.nbu.pojo.Student">
        <property name="name" value="阿昌"/>
        <property name="address" ref="address"/>
    </bean>
		-->
    <bean id="student" class="com.nbu.pojo.Student" autowire="byName">
        <property name="name" value="阿昌"/>
    </bean>

</beans>

运行结果如下
在这里插入图片描述
这就完成了通过属性名完成自动注入,我们接下来使用第二种方式byType完成属性注入

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

    <bean id="address" class="com.nbu.pojo.Address">
        <property name="country" value="中国"/>
        <property name="province" value="福建省"/>
    </bean>

		<!--这里修改一下autowire后面的值就行了-->
    <bean id="student" class="com.nbu.pojo.Student" autowire="byType">
        <property name="name" value="阿昌"/>
    </bean>

</beans>

感觉是不是很简单,这里我要说一下注意点,就是byType必须保证找到的结果是唯一的,不然就会报错。

五、代理模式
为什么要说这个呢?那是因为AOP的原理实际上就是代理模式,理解代理模式后对于AOP的理解会更加的容易。
代理模式主要分为两种,一种是静态代理,一种是动态代理,不过其本质都是在不改变原来已有的代码的情况下实现方法的增强。
我们先来看静态代理,首先我们来做一些准备,建立一个原本实际的Real类和代理Proxy类和一个接口CanDo表示能做些什么。
分别如下:
public interface CanDo {
    public void Do();
}

public class Real implements CanDo{
    public void Do(){
        System.out.println("Real 做了一些事情");
    }
}
public class Proxy implements CanDo{
    private CanDo real;
    public void SetPro(CanDo real)
    {
         this.real = real;
    }

    public void Do()
    {
        if (real!= null)
        {
            System.out.println("前置的增强");
            real.Do();
            System.out.println("后置的增强");
        }

    }
}

测试代码和运行结果如下:

public class Test {
    public static void main(String[] args) {
        Real real = new Real();
        Proxy proxy = new Proxy();
        proxy.SetPro(real);
        proxy.Do();
    }
}

在这里插入图片描述
这种方式就是静态代理,动态代理的话,是通过Java的反射来做的,和静态代理的实现是差不多的,接下来我们就在静态代理基础上做些改动来实现动态代理

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class Proxy implements InvocationHandler{
    private CanDo real;

    public void SetProxyObject(CanDo real)
    {
        this.real =real;
    }

    public Object GetPro()
    {
        return java.lang.reflect.Proxy.newProxyInstance(this.getClass().getClassLoader(),real.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前置增强");
        method.invoke(real,args);
        System.out.println("后置增强");
        return null;
    }
    
}
public class Test {
    public static void main(String[] args) {
        CanDo real = new Real();
        Proxy proxy = new Proxy();
        proxy.SetProxyObject(real);
        CanDo canDo = (CanDo) proxy.GetPro();
        canDo.Do();
    }
}

输出结果

在这里插入图片描述
了解了代理模式后,我们就可以来学习AOP了。

六、什么是AOP
AOP又叫做面向切面编程,我们可以借助上面的代理模式来理解这一概念。 我们先来理解几个概念
(以下内容引用自狂神说)

切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类
通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
目标(Target):被通知对象。
代理(Proxy):向目标对象应用通知之后创建的对象。
切入点(PointCut):切面通知 执行的 “地点”的定义。
连接点(JointPoint):与切入点匹配的执行点。

在这里插入图片描述

我们接下来就使用尝试一下在Spring当中使用AOP。使用AOP之前,我们先要导入一些jar包,以及一些AOP的约束

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

</beans>

这里我们使用Spring的API来实现,当然可以自定义,之后会演示。我们现在先写两个切面Before和After以及一个目标Temp

package com.nbu.Annocation;

import org.aopalliance.aop.Advice;
import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Before implements MethodBeforeAdvice {

    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("前置通知");
    }
}
package com.nbu.Annocation;

import org.springframework.aop.AfterAdvice;
import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class After implements AfterReturningAdvice {

    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("后置通知");
    }
}

package com.nbu.Dao;

public class Temp {
    public void Test(){
        System.out.println("连接点。。。");
    }
}

当然写完后要注册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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="user" class="com.nbu.pojo.User">
        <property name="username" value="root"/>
        <property name="password" value="123456789"/>
    </bean>

    <bean id="address" class="com.nbu.pojo.Address">
        <property name="country" value="中国"/>
        <property name="province" value="福建省"/>
    </bean>

    <bean id="student" class="com.nbu.pojo.Student" autowire="byType">
        <property name="name" value="阿昌"/>
    </bean>

    <bean id="temp" class="com.nbu.Dao.Temp"/>
    <bean id="before" class="com.nbu.Annocation.Before"/>
    <bean id="after" class="com.nbu.Annocation.After"/>

    <aop:config>
        <aop:pointcut id="testPointCut" expression="execution(* com.nbu.Dao.Temp.*(..))"/>
        <aop:advisor advice-ref="before" pointcut-ref="testPointCut"/>
        <aop:advisor advice-ref="after" pointcut-ref="testPointCut"/>
    </aop:config>

</beans>

我们测试一下

package com.nbu;

import com.nbu.Dao.Temp;
import com.nbu.pojo.Student;
import com.nbu.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
       ApplicationContext Context =new  ClassPathXmlApplicationContext("springDao.xml");
       Temp temp = Context.getBean("temp", Temp.class);
       temp.Test();
    }
}

结果如下

在这里插入图片描述
如果是要自定以的话,我们就要去写一个类这个类不用继承任何的接口

public class TestAop{
	public void Before(){
		System.out,println("前置通知");
	}
	public void After(){
		System.out.println("后置通知");
	}
}

同时,xml文件里的配置要变为

<bean id="testApp" class"com.nbu.TestApp">
    <aop:config>
   		 <aop:aspect ref="testApp">
	        <aop:pointcut id="testPointCut" expression="execution(* com.nbu.Dao.Temp.*(..))"/>
	        <aop:advisor method="Before" pointcut-ref="testPointCut"/>
	        <aop:advisor method="After" pointcut-ref="testPointCut"/>
     	 </aop:aspect>
    </aop:config>

结果和上面是一样的。

七、整合Mybatis框架
如果你不知道Mybatis的话可以去看一下我之前写的,做一个简单的了解

https://blog.csdn.net/qq_52239796/article/details/122650482?spm=1001.2014.3001.5501

我们接下来,来接着介绍。在开始之前,我们依旧要做一些准备,先导入一个jar包。

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.7</version>
        </dependency>

当然对于这个jar包的导入版本,和你其他jar包导入的版本是有关联的

此图来自官网我们还要导入数据库相关的jar包,还有连接需要的jar包

        <!-- pool -->
        <dependency>
            <groupId>commons-pool</groupId>
            <artifactId>commons-pool</artifactId>
            <version>1.6</version>
        </dependency>
        <!-- dbcp依赖包 -->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
        <!--dbcp2依赖包-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-dbcp2</artifactId>
            <version>2.0.1</version>
        </dependency>
         <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.8</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>

这样我们的环境就搭建好了,接下来,我就就在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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
		<!--配置数据源-->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://127.0.0.1/stu"/>
        <property name="username" value="输入用户名"/>
        <property name="password" value="输入密码"/>
    </bean>
		<!--建立SqlSession工厂-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:com/nbu/Dao/*.xml"/>
    </bean>
		<!--得到SqlSessionTemplate,就是SqlSession-->
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg  ref="sqlSessionFactory"/>
    </bean>

    <bean id="user" class="com.nbu.pojo.User">
        <property name="username" value="root"/>
        <property name="password" value="123456789"/>
    </bean>

    <bean id="address" class="com.nbu.pojo.Address">
        <property name="country" value="中国"/>
        <property name="province" value="福建省"/>
    </bean>

    <bean id="student" class="com.nbu.pojo.Student" autowire="byType">
        <property name="name" value="阿昌"/>
    </bean>

    <bean id="temp" class="com.nbu.Dao.Temp"/>
    <bean id="before" class="com.nbu.Annocation.Before"/>
    <bean id="after" class="com.nbu.Annocation.After"/>

    <aop:config>
        <aop:pointcut id="testPointCut" expression="execution(* com.nbu.Dao.Temp.*(..))"/>
        <aop:advisor advice-ref="before" pointcut-ref="testPointCut"/>
        <aop:advisor advice-ref="after" pointcut-ref="testPointCut"/>
    </aop:config>
</beans>

接下来的操作就和使用Mybatis差不多了,Spring中的配置其实就是代替了mybatis-config.xml,不过我们还是保留mybatis-config.xml来进行一些别名、插件、设置之类的配置。
我们从Spring中去请求SqlSessionTemplate然后通过其获得Mapper,再通过Mapper获得接口,通过接口去使用自己在Mapper中实现的SQL语句就行了。这里就不演示了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值