Spring配置

github上下载源码zip

在maven里导包 spring-mvc

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.32</version>
</dependency>

IOC 控制反转

AOP 面向切面编程

spring必须要有set方法,只有这样才能实现控制反转。

核心配置文件

<?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="..." class="...">  
        <!-- 这个bean的合作者和配置在这里 -->
    </bean>

    <bean id="..." class="...">
        <!-- c这个bean的合作者和配置在这里 -->
    </bean>

    <!-- 更多bean 定义在这里 -->

bean就是spring里的对象,对象不用new了,通过spring创建。

配置

bean配置

import:

在一个配置文件里导入其他配置文件,以此合并为一个

别名

依赖注入

1.构造器注入

需要有构造函数

2.set注入

需要有set方法!

3.拓展方式注入

各种注入方式

(同一个id的注入要写在一个里面,不可以分开写)

    <bean id="student" class="com.li.pojo.Student">
        <!--  普通值注入-->
        <property name="name" value="小李"/>
        <!--    bena注入-->
        <property name="address" ref="address"/>
        <!--    数组注入-->
        <property name="books">
           <array>
               <value>三国演义</value>
               <value>水浒传</value>
               <value>红楼梦</value>
               <value>西游记</value>
           </array>
        </property>
<!--        List注入-->
        <property name="hobbies">
            <list>
                <value>唱</value>
                <value>跳</value>
                <value>rap</value>
            </list>
        </property>

<!--        map注入-->
        <property name="card" >
            <map>
                <entry value="1" key="2"/>
            </map>
        </property>

<!--        set注入-->
        <property name="games">
            <value>sada</value>
        </property>

<!--        null注入-->
        <property name="wife" value=""/>

<!--        properties注入-->
        <property name="info">
            <props>
                <prop key="1">13</prop>
            </props>
        </property>
    </bean>

p命名和c命名

p命名可以直接注入属性的值

p配置导入

  xmlns:p="http://www.springframework.org/schema/p"

编写规范

    <bean id="user" class="com.li.pojo.User" p:name="小李" p:age="18"/>

c命名,类似于有参构造器注入

c配置导入

xmlns:c="http://www.springframework.org/schema/c"

编写规范

 <bean id="user2" class="com.li.pojo.User" c:name="小李" c:age="18"/>

设计模式

单例模式:所有对象指的都是同一个(spring默认模式)

原型模式:每个对象都是独立的

......

自动装配

auto wire

byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid;

byType:对象属性相同的bean

使用注解实现自动装配

1.导入约束(配置注解支持)

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

    <context:annotation-config/>

</beans>

@Autowired:

直接在属性上使用即可,也可以在set方式上使用

使用Autowired 我们可以不用编写Set方法了,前提是配置正确,且名字一样,实际上还是根据byType,但可以不用set方法了。

@Qualifier,

指定装配

前面两个是配套的spring的注解

@resource

是java注解,不推荐

@Nullable

该字段可以为空

使用注解开发

1.导入aop,xml里需要有注解支持

@Component 主键,等价于在xml注册一个bean

@Value,给属性赋值

和Component一样的注解如下,只是不同层习惯用不同注解

dao @Repository

service @Service

controller @Controller

@Scope

代理模式

静态代理

​ 有一个代理类(自己生成)

​ 不改变原先代码,而是增加一个代理对象,那就不会对原先代码产生影响,属于解耦过程

不改变原先代码,就实现要增加功能的目标

动态代理(代理的是一个接口)

角色和静态代理一样

代理类是动态生成的,不是直接写好

两大类:基于接口(JDK),基于类(cglib),java字节码(Javasist)

基于接口

工具类(万能的):

package com.li.demo02;

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

//用于动态创建代理对象
public class CreateProxy implements InvocationHandler {
   //用于接收一个要实现接口
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }
    //获得一个代理对象
    public Object getProxy()
    {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
    }

    //对产生的这个类进行加工,要是不加工就是返回一个和真实对象一样的代理对象
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(target,args);

        return result;
    }
}

实现的过程

package com.li.demo02;

public class Client {
    public static void main(String[] args) {
        UserServiceImp01 userServiceImp01 = new UserServiceImp01();//必须有一个真实对象

        CreateProxy proxy = new CreateProxy();
        proxy.setTarget(userServiceImp01);//放入真实对象以获取代理

        UserService01 proxy1 = (UserService01) proxy.getProxy();

        proxy1.add();
    }





}

AOP

底层就是动态代理

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

    <!-- bean definitions here -->

导入依赖

除了aop还要导入这个依赖

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.22</version>
    <scope>runtime</scope>
</dependency>

方法一:使用Spring的API接口(通过类实现接口)

aop的配置切点和执行环绕

  <aop:config>
<!--        切入点-->
<aop:pointcut id="pointcut" expression="execution(* com.li.pojo.UserServiceImp.*(..))"/>
<!--执行环绕-->
        <aop:advisor advice-ref="add" pointcut-ref="pointcut"/>
    </aop:config>

方法二:自定义类(切面) 简单一点(通过xml里的切面配置)

    <bean id="prase" class="com.li.dao.Prase"/>
    <aop:config>
        <aop:aspect ref="prase">
            <aop:pointcut id="pointcut" expression="execution(* com.li.pojo.UserServiceImp.*(..))"/>
            <aop:before method="before" pointcut-ref="pointcut"/>
            <aop:after method="after" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>

方式三:注解实现

需要导入aspectj依赖

 <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        
    </dependency>

在xml里开启自动aop

<aop:aspectj-autoproxy/>

直接在类里实现

package com.li.dao;


import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class Test01 {
    @Before(value = "execution(* com.li.pojo.UserServiceImp.*(..))")
    public void before()
    {
        System.out.println("执行前");
    }
    @After(value = "execution(* com.li.pojo.UserServiceImp.*(..))")
    public void after()
    {
        System.out.println("执行后");
    }


}

整合Mybatis

https://mp.weixin.qq.com/s/gXFMNU83_7PqTkNZUgvigA

导入依赖

  <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.10.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>

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



    </dependencies>

beans.xml的配置

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url"
                  value="jdbc:mysql://localhost:3306/mybatis?useSSl=true&useUnicode=true&characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>

    <!--配置SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!--关联Mybatis-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:com/li/mapper/UserMapper.xml"/>
    </bean>

    <!--注册sqlSessionTemplate , 关联sqlSessionFactory-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--利用构造器注入-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

    <bean id="userDao" class="com.li.mapper.UserDaoImp">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>

实现类的编写

package com.li.mapper;

import com.li.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.List;

public class UserDaoImp implements UserMapper {
    //sqlSession不用我们自己创建了,Spring来管理
    private SqlSessionTemplate sqlSession;

    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }

    @Override
    public List<User> getUsers() {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        return mapper.getUsers();
    }
}

声明性事务

事物的ACID原则:原子性,一致性,隔离性,持久性

声明性事务:AOP

​ 事务xml配置以及aop织入

<bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
 <tx:advice transaction-manager="transactionManager" id="interceptor">
     <tx:attributes>
         <tx:method name="add" propagation="REQUIRED"/>
         <tx:method name="update" propagation="REQUIRED"/>
         <tx:method name="delete" propagation="REQUIRED"/>
         <tx:method name="select" propagation="REQUIRED"/>
     </tx:attributes>
 </tx:advice>

    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.li.Dao.*.*(..))"/>
        <aop:advisor advice-ref="interceptor" pointcut-ref="pointcut"/>
    </aop:config>

编程式事务:会影响原来的代码

不推荐,不用