Spring Framework

github resolve spring-projects/spring-framework#27432. Added Assert.isFalse … by Melancholic · Pull Request #27514 · spring-projects/spring-framework · GitHub

spring官网  Spring Framework

spring下载地址  http://repo.spring.io/release/org/springframework/spring

spring中文文档   https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/#

meavn Spring web MVC依赖包

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

1.2优点

轻量级 非入侵式IOC 控制反转AOP面向切面编程的框架

1.3组成

1.4 拓展

Spring Boot

   快速开发脚手架,快速开发单个微服务

  约定大于配置

Spring Cloud

  基于Spring Boot实现的

2 IOC理论推导

 1.UserDao接口

 2.UserDaoImpl实现类

2.1UserDaoMysqlImpl实现类

 3.UserService业务接口

 4.UserServiceImpl业务实现类

以前没有在UserServiceImpl中建立set方法,需要程序员管理对象的创建。

 private UserDao userDao=new UserDaoImpl();
 UserService userService=new UserServiceImpl();
       // ((UserServiceImpl) userService).setUserDao(new UserDaoImpl());
        userService.getUser();

 

在UserServiceImpl中建立set方法动态选择注入 UserDao接口的实例对象

使得选择权放在了用户手中

这种变化相当于控制反转,从原来的我们管理对象的创建到被动的接受对象,系统耦合性降低。

/        用户调用业务层不接触Dao层
        UserService userService=new UserServiceImpl();
        ((UserServiceImpl) userService).setUserDao(new UserDaoImpl());
        userService.getUser();
  private UserDao userDao;

    public UserDao getUserDao() {
        return userDao;
    }
//利用set控制值的注入
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

ioc是Spring框架的核心内容,使用很多方式完美的实现了Ioc,可以使用xml配置,亦可以使用注解,新版本的Spring也可以零配置实现Ioc。

控制反转ioc是一种描述(XML或者注解)并通过第三方去生产或产生特定的对象。在Sring中实现控制反转的是ioc容器,其实现方式是依赖注入(Dependency injection DI)。

代码Spring-01-ioc

 beans.xml

<!--使用Sring来创建对象,在Spring这些都成为Bean-->
<!--bena=对象
类型 变量名=new 类型();
Hello hello=new Hello();
id hello
class =new 的对象
property 给对象设值

-->
<?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="userDaoImpl" class="com.yang.dao.UserDaoImpl"/>
        <bean id="userDaoMysqlImpl" class="com.yang.dao.UserDaoMysqlImpl"/>
    <bean id="userServiceImpl" class="com.yang.service.UserServiceImpl">
        <!--ref设置引用值-->
        <property name="userDao" ref="userDaoMysqlImpl">

        </property>
    </bean>
</beans>

4.ioc创建对象的方式

    1 默认使用无参构造

  2 假设我们使用有参构造

   1 构造参数索引  String是引用数据类型 ,但是用value

 <!--<constructor-arg index="0" value="王java"/>-->
        <!--<constructor-arg index="1" value="12"/>-->

         2使用构造参数类型

 <!--<constructor-arg type="java.lang.String" value="wang"/>-->
        <!--<constructor-arg type="int" value="12"/>-->

        3使用构造参数名

 <constructor-arg name="name" value="wcy" />
        <constructor-arg name="age" value="12"/>

在配置文件加载的时候。容器管理的对象的就已经初始化了,不管你用不用

5.spring配置

  5.1 alias 别名 给bean id换个称呼 原来的别名都能使用

  <alias name="user" alias="wang"/>

       5.2 bean配置

 <!--
           id :bean的唯一标识符,相当于对象名
           class ;bean 对象所对应的全限定名: 包名+类名
           name 可以同时取很多个别名
    -->
    <bean id="user" class="com.yang.pojo.User" name="user2 user3 user4;user5,user6" >

  5.3 import 用于团队开发,把多个配置文件导入合并为一个重复的只取一份

 

<?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="beans.xml"/>
</beans>

6 ,依赖注入

 6.1 构造器注入

 6.2 set注入

  依赖 bean对象的创建依赖于容器

  注入 bean对象中的所有属性,由容器来注入

 1复杂环境

package com.yang.pojo;

public class Address {
    private String address;

    public String getAddress() {
        return address;
    }

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

 

2 真实测试对象

   String name;
    Address address;
    String[] books;
    List<String> hobbys;
    Map<String,String> card;
    Set<String> games;
    String wife;
    Properties info;

 

3 beans.xml            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 http://www.springframework.org/schema/beans/spring-beans.xsd">
   <bean id="address" class="com.yang.pojo.Address">
       <property name="address" value="石家庄"/>
   </bean>
    <bean id="student" class="com.yang.pojo.Student">
        <!--普通值注入-->
        <property name="name" value="wang"/>
        <!--引用类型注入-->
        <property name="address" ref="address"/>
        <!--数组注入-->
        <property name="books">
            <array>
                <value>大秦帝国</value>
                <value>红楼梦</value>
                <value>西游记</value>
            </array>
        </property>
        <!--List集合注入-->
        <property name="hobbys">
            <list>
                <value>羽毛球</value>
                <value>打游戏</value>
            </list>
        </property>
        <!--entry实体的意思 里面由键值对-->
        <property name="card">
            <map>
                <entry key="身份证" value="1309231998777777555"/>
                <entry key="银行卡" value="5418854188"/>
                <entry key="姓名" value="哇啊啊啊"/>
            </map>
        </property>
        <!--set注入-->
        <property name="games">
            <set>
                <value> 英雄联盟</value>
                <value>永结无间</value>
            </set>
        </property>
        <!--null值注入-->
        <property name="wife" >
            <null/>
        </property>
        <!--Properties配置类-->
        <property name="info">
            <props>
                <prop key="学号" >20192525</prop>
                <prop key="姓名">王万年</prop>
                <prop key="性别"></prop>
            </props>
        </property>



    </bean>
</beans>

 

 

4 测试类

import com.yang.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Student student=(Student) context.getBean("student");
        System.out.println(student.toString());


    }
}

 6.3拓展方式注入

  p 命名注入   导入约束 

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

p-namespace 允许您使用bean元素的属性(而不是嵌套的<property/>元素)来描述协作 Bean 的属性值,或同时使用这两者

  <bean id="user" class="com.yang.pojo.User" p:name="wang" p:age="18"/>

 

  C 命名注入  有参构造 导入约束

        

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

与具有 p-命名空间的 XML 快捷方式相似,在 Spring 3.1 中引入的 c-namespace 允许使用内联属性来配置构造函数参数,而不是嵌套的constructor-arg元素。

  

<bean id="user" class="com.yang.pojo.User" c:name="wa" c:age="17"/>

测试类

 @Test
    public void Test2(){
        ApplicationContext context = new ClassPathXmlApplicationContext("UserBeans.xml");
        User user=context.getBean("user",User.class);
        System.out.println(user.toString());
    }

6.4 bean的作用域

                                   

 单例模式

 

<bean id="user" class="com.yang.pojo.User" c:name="wa" c:age="17" scope="prototype"/>

 

 

 

 ApplicationContext context = new ClassPathXmlApplicationContext("UserBeans.xml");
        User user=context.getBean("user",User.class);
        User user2=context.getBean("user",User.class);
        System.out.println(user==user2);

  

 如果不默认单例模式,换位原型模式 结果为false

<bean id="user" class="com.yang.pojo.User" c:name="wa" c:age="17" scope="prototype"/>

  

 2 原型模式 : 每次getBean产生一个新的对象!

<bean id="user" class="com.yang.pojo.User" c:name="wa" c:age="17" scope="prototype"/>

 

3 其余的 request session application,只能在web开发中使用到

  7 bean的自动装配  

  自动装配式Spring满足bean依赖的一种方式!自动在上下文中寻找,给Bean装配

  1 在xml显示配置

  2 在java中显示配置

  3 隐式的自动装配 重要

 7.1 环境搭建

   一个人有两个宠物

       7.2 Byname自动装配 需要 bean的id唯一    通过 自己对象的getXxx方法的Xxx去找到装配的  (需要bean的id属性和Xxx保持一致)

 <bean id="people" class="com.yang.pojo.Person" autowire="byName">

 

       7.3 ByType 会自动在容器上下文中查找和自己属性类型相同beanid   保证bean的class唯一,并且这个bean需要和自动注入的属性类型一致

<bean id="people" class="com.yang.pojo.Person" autowire="byType">

  7.4  使用注解进行自动装配

         jdk1.5 支持的注解 spring2.5开始

  1 导入约束    context约束

  2 配置注解支持

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">

    <context:annotation-config/>
       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
">
<!--开启注解的支持-->
    <context:annotation-config/>
    <bean id="cat" class="com.yang.pojo.Cat"/>
    <bean id="dog" class="com.yang.pojo.Dog"/>
    <bean id="people" class="com.yang.pojo.People" />
public class MTest {
    @Test
    public void Test1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
       People people=(People) context.getBean("people");
       people.getDog().shout();
       people.getCat().shout();
    }
}

注解使用反射来实现的可以没由set方法

@Autowired 按类型

@Autowirde(required =false) 这个对象可以为空,没有这个参数则不允许

package com.yang.pojo;

import org.springframework.beans.factory.annotation.Autowired;

public class People {
    @Autowired
    private  Cat cat;
    @Autowired
    private  Dog dog;
    private  String name;

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "People{" +
                "cat=" + cat +
                ", dog=" + dog +
                ", name='" + name + '\'' +
                '}';
    }
}
package com.yang.pojo;

public class Cat {
    public void shout(){
        System.out.println("喵~");
    }
}
package com.yang.pojo;

public class Dog {
    public void shout(){
        System.out.println("汪~");
    }
}

测试类不能与运行没有导入

<groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>

@Nullable 标记了这个字段说明这个字段可以为Null

public People(@Nullable String name) {
        this.name = name;
    }

@Autowirde(required =false) 这个对象可以为空,没有这个参数则不允许

 

@Qulifier 自动装配的环境比较复杂 我们可以用它去配合Autowired的使用,制定一个唯一的bean对象注入

@Autowired
    @Qualifier(value = "cat1")
    private  Cat cat;
<context:annotation-config/>
    <bean id="cat1" class="com.yang.pojo.Cat"/>
    <bean id="cat2" class="com.yang.pojo.Cat"/>

@Resource java的注解 名字和类型有一个唯一就可以  也可以这样

@Resource(name = "cat1")
 @Resource
    private  Cat cat;
    @Autowired
    private  Dog dog;
    private  String name;
<context:annotation-config/>
    <bean id="cat1" class="com.yang.pojo.Cat"/>
    <bean id="dog" class="com.yang.pojo.Dog"/>
    <bean id="people" class="com.yang.pojo.People" />

8 使用注解开发

  在Spring4之后,要使用注解开发,必须保证aop的包导入了

  

 

使用注解需要的导入context约束,增加注解的支持  

 

1 bean

  

  2属性如何注入

package com.yang.dao;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//等价于<bean id="对象" class="全类名"/>
//@Component :组件
@Component
public class User {
    //相当于<property name="name" value="王阳"/>
    @Value("王阳")
    public String name;
}

 

  3衍生的注解

  @Component有几个衍生注解,我们在web开发中,按MVC

   。dao【@Repository】

   。service【@Service】

    。controller【@Controller】

    这几个和@component功能一样,都是带表将某个类注册到Spring容器中,装配Bean

  4自动装配

    见上面@Autowired部分

  5bean作用域

   @Scop

@Repository
//标注模式 现在标注的是单例模式 作用域
@Scope("singleton")
public class User {
    //相当于<property name="name" value="王阳"/>
    @Value("王阳")
    public String name;
}

 

  6小结

            xml与注解

      xml更加万能,适用于任何场合!维护简单方便

        注解 不是自己得累使用不了 ,维护复杂!

          xml与注解最佳实践 

            xml用来管理bean   

            注解负责完成属性的注入

            使用过程,只需要注意一个问题:必须让注解生效,就需要开启注解的支持

<!--指定要扫描的包,这个包下的注解就会生效-->
    <context:component-scan base-package="com.yang"/>
    <context:annotation-config/>

          

 在 Java 代码中使用注解来配置 Spring 容器

    <!--指定要扫描的包,这个包下的注解就会生效-->
  
     <!--component 组件-->

<context:component-scan base-package="com.yang.pojo"/> <context:annotation-config></context:annotation-config>

9 使用Java的方式配置Spring

  我们现在要完全不适用Spring的XML配置了,全权交给Java来做。

  JavaCofig(推荐 更加灵活,在Spring4之后成为了一个核心功能)是Spring的一个子项目,

 

 

 

配置文件
package
com.yang.config; import com.yang.pojo.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration //本身就是一个配置,这个也会被Spring容器托管,注册到容器中,因为它本来就是一个@Component。 // 代表这是一个配置类,和beans.xml一样 @ComponentScan("com.yang.pojo" ) //扫描包 @Import(YangConfig2.class)//把两个引成一个类 public class YangConfig { //注册一个Bean,就相当于我们之前写的一个Bean标签 //这个方法的名字= bean的id //这个方法的返回值=bean的 class @Bean //方法名就是Bean的名字 public User getUser(){ return new User();//返回到Bean中的对象! } }
实体类
package
com.yang.pojo; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; //需要放到Spring中的类 //讲的是说明这个类被Spring类接管了,注册到了容器中 但是我实测不加也没事 @Component public class User { private String name; @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; } public String getName() { return name; } @Value("王阳")//属性注入值 public void setName(String name) { this.name = name; } }
配置文件
package
com.yang.config; public class YangConfig2 { }



测试类
import
com.yang.config.YangConfig; import com.yang.pojo.User; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MyTest { public static void main(String[] args) { //如果完全使用了配置类去做,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载 ApplicationContext context = new AnnotationConfigApplicationContext(YangConfig.class); //方法名就是Bean的名字 User getUserr = context.getBean("getUser", User.class); System.out.println(getUserr.getName()); } }

 纯java的配置方式,在SpringBoot中随处可见

 10 AOP 面向切面编程

    动态代理模式是AOP的底层,有两种JDK 和cglib两种,这里我们用静态代理先引入一下

 

      静态代理

                   角色分析:

              抽象角色:一般使用接口或者抽象类

package com.yang.demo01;

public interface Rent {
    public void rent();
}

  

              真实角色:被代理的角色

package com.yang.demo01;
//房东
public class Host implements Rent{
    public void rent(){
        System.out.println("房东要出租房子");
    }
}

  

              代理角色: 代理真实角色(依赖)会增加一些附属操作

package com.yang.demo01;

public class Proxy implements rent{
//先用组合,后用继承
private Host host;

public Proxy(Host host) {
this.host = host;
}

public Proxy() {
}
public void rent(){
seeHouse();
host.rent();
fare();
}
//附加操作
public void seeHouse(){
System.out.println("带你看房");
}
public void fare(){
System.out.println("收中介费");
}
}

              客户: 访问代理对象的人 客户端访问代理角色

package com.yang.demo01;

public class Client {
    public static void main(String[] args) {
        Host host=new Host();
        //代理 代理角色会增加附属操作
        Proxy proxy=new Proxy(host);
        //不用面对房东,直接找中介租房
        proxy.rent();
    }
}

  

优点

代理模式的好处,可以使真实角色的操作更加纯粹!不用去关注公共的业务

公共交给代理角色!实现了业务的分工!

公共业务扩展时,方便集中管理!

缺点

一个真实角色会产生一个代理角色;代码量会翻倍

 

 

      动态代理

  动态代理和静态代理角色一样

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

  动态代理两个类:基于接口的动态代理    基于类的动态代理

    。基于接口----JDK动态代理

    。基于类:cglib

    。java字节码实现: javasist 快速简单的改变类的结构,或生成动态类

需要了解的两个类:Proxy 代理 ,InvocationHandler 调用处理程序

 

动态代理的好处;包含静态的优点,一个动态代理类代理的是一个接口,一般就是对应的一类业务 。

        一个动态代理类可以代理多个类,主要实现了同一个接口即可;

动态代理生成类

package com.yang.demo04;

import com.yang.demo03.Rent;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//Proxy类生成动态代理实例的 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类
//InvocationHandler调用处理程序并返回一个结果的 是代理实例的调用处理程序 实现的接口。每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。
//我们会用这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
    //被代理的接口
    //变成一个更加灵活的Object
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    //生成得到代理类
   public Object getProxy(){
       return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
   }

    //处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       //动态代理的本质,就是使用反射机制实现!
        log(method.getName());
       Object result=method.invoke(target,args);

        return result;
    }
        public void log(String msg){
        System.out.println("执行了"+msg+"方法");
    }


}

  客户端调用动态代理生成类

package com.yang.demo04;

import com.yang.demo02.UserService;
import com.yang.demo02.UserServiceImpl;

public class Client {
    public static void main(String[] args) {
        //真实角色
        UserServiceImpl userService=new UserServiceImpl();
        //代理角色不存在
        ProxyInvocationHandler proxyInvocationHandler=new ProxyInvocationHandler();
        proxyInvocationHandler.setTarget(userService);//设置要代理的对象
        //动态生成代理类
        UserService proxy=(UserService)proxyInvocationHandler.getProxy();
        proxy.add();
        proxy.delete();
    }
}

  抽象类

package com.yang.demo05;

public interface UserService {
    public void add();
    public void update();
    public void delete();
    public void query();
}

  真实角色

package com.yang.demo05;

public class UserServiceImpl implements UserService{
    public void add(){
        System.out.println("增加了一个用户");
    }

    public void delete() {
        System.out.println("删除了一个用户");
    }

    public void query() {
        System.out.println("遍历用户");
    }

    public void update() {
        System.out.println("更新了一个用户");
    }
}

 11 AOP(Aspect Oriented Programming) 面向切面编程,函数式编程的一种衍生范型。通过预编译方式和运行期动态代理实现程序功能维护的一种技术;

    横切关注点: 跨越应用程序多个模块的方法或者功能。即是,与我们的业务逻辑无关,但是需要我们关注的部分,就是横切关注点。如 日志,安全,缓存,事物等。。(中介附加的功能)

    切面(Aspect):横切关注点,被模块化的特殊对象。它是一个类  Log.class

    通知(Advice):切面必须要完成的工作,它是一个方法。Log方法

    目标(Target):被通知对象 想要用的真实角色实例化对象  log

    代理(Proxy):向目标对象应用通知创建的对象

    切入点(PointCut):切面通知 执行的“地点”的定义   method.invoke(target.args)

    连接点(JionPoint):与切面匹配的执行点

  使用Aop织入,需要导入依赖包

    

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

      <version>1.9.4</version>  
        </dependency>

方式一: 使用spring的API接口

 日志增强前置类

  

package com.yang.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;
//日志增强类 前置
public class Log  implements MethodBeforeAdvice {
   //method   要执行的的目标对象的方法
    //objects 参数  args
   // o 相当于 target 目标对象
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        //我们可以知道目标对象执行了什么方法
        System.out.println(o.getClass().getName()+"的"+method.getName()+"被执行了");

    }
}

日志增强后置类’

package com.yang.log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;
//日志增强类 后置
public class AfterLog implements AfterReturningAdvice {
    //returnValue 返回值
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了" + method.getName() + "方法+反回结果为" + returnValue);
    }
}

application'Context.XML  getBean 配置

<?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
       https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--注册bean-->
    <bean id="userService" class="com.yang.service.UserServiceImpl"/>
    <bean id="log" class="com.yang.log.Log"/>
    <bean id="afterLog" class="com.yang.log.AfterLog"/>
   <!--方式一 :使用原生的spring API接口-->
    <!--配置Aop: 需要导入AOP的约束-->
    <aop:config>
        <!--首先需要一个切入点,我们要在那个地方执行 expresion(要执行的位置 publc修饰词  返回值 类名 方法名 参数) :表达式-->
        <!--(..)代表任意的参数-->
        <aop:pointcut id="pointcut" expression="execution(* com.yang.service.UserServiceImpl.*(..))"/>
        <!--执行环绕增强-->
        <!--advice-ref 引用自哪里  把log 切入到 👆 id= pointcut 方法上面 增强哪个类切入到哪里-->
        <aop:advisor advice-ref="log"  pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>
</beans>

抽象类 和切面类自己设置 我这里写的是 接口 UserService 切面类 UserServiceImpl

测试类

import com.sun.org.apache.bcel.internal.generic.NEW;
import com.yang.service.UserService;
import com.yang.service.UserServiceImpl;
import org.aspectj.weaver.ClassAnnotationValue;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MTest {
    public static void main(String[] args) {
        //new ClassPathXmlApplicationContext() 获取ClassPath获取类路径的xml文件
        //纯java配置
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //动态代理代理的是接口  代理的是一类接口
        UserService userService=(UserService) context.getBean("userService");
        userService.add();
    }
}

方法二  自定义来实现Aop

  

<bean id="diy" class="com.yang.diy.DiyPointCut"/>
    <aop:config>
        <!--自定义切面 ,ref要引用得类  -->
        <aop:aspect ref="diy">
            <!--切入点-->
            <aop:pointcut id="point" expression="execution(* com.yang.service.UserServiceImpl.*(..))"/>
            <!--通知-->
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>

方式三 通过注解来实现

 切面类

package com.yang.diy;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

//使用注解方式来实现AOP
@Aspect //标注这个类是一个切面
public class AnnotationPointCut {
    @Before("execution(* com.yang.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("方法执行前");
    }
    @After("execution(* com.yang.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("方法执行后");
    }
    //在环绕强中,我们可以给定一个参数,代表我们我们要获取处理的切入点
    @Around("execution(* com.yang.service.UserServiceImpl.*(..))")
    //ProceedingJoinPoint 与切入点匹配的执行点
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("环绕前");
        Signature signature=jp.getSignature();//获得签名
        System.out.println("Signature" + signature);
        //执行方法
        Object proceed=jp.proceed();
        System.out.println("环绕后");
    }
}
<!--方式三-->
    <bean id="annotationPointCut" class="com.yang.diy.AnnotationPointCut"/>
    <!--开启注解支持!   JDK(默认proxy-target-class="false)   cglibproxy-target-class="true-->
    <!--切面自动代理-->
    <aop:aspectj-autoproxy proxy-target-class="false"/>

 

12 整合MyBatis

  1 导入jar包 junit单元测试   mybatis mysql Spring   aop织入  mybtis-sprin【new】

    

<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.45</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.10</version>
        </dependency>
        <!--Spring操作数据库,需要一个Spring-jdbc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.3.14.RELEASE</version>
        </dependency>
        <!--AOP织入包-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
        <!--mybatis整合spring的包-->
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>


    </dependencies>

configuration核心配置文件

<?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核心配置文件-->
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

maven静态资源过滤问题

 

  <build>
      <resources>
          <resource>
              <directory>src/main/java</directory>
              <includes>
                  <include>**/*.xml</include>
              </includes>
              <filtering>true</filtering>
          </resource>
      </resources>
  </build>

 

 

1 编写实体类

2 编写核心配置文件

3 编写接口

4 编写 Mapper.xml

5测试

12.2  MyBatis-Spring

   说明网站   

http://mybatis.org/spring/zh/index.html

方法一 SqlSessionTemplate

spring-dao.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
       https://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--DataSource: 使用Spring的数据源替换MyBatis的配置
      这里我们使用Spring提供的JDBC还能用c3p0 dbcp druid-->
    <!--数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </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/yang/mapper/UserMapper.xml"/>
    </bean>
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
       <!--只能使用构造器注入sqlSessionFactor,因为它没有set方法-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>

    </bean>

</beans>
public class UserMapperImpl implements UserMapper {
   //我们的所有操作都是用sqlSession来执行,现在都是用sqlSessionTemplate
   private SqlSessionTemplate sqlSession;

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

    public List<User> selectUser() {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        return mapper.selectUser();
    }
    //我们的所有操作,都使用SqlSession来执行,在原来,现在都使用sqlSeesionTemplace
}

  

1 编写数据源

2 SqlSessionFactory

3 sqlSessionTemplate

4 给接口加实现类

5将自己写的类注入到Spring中

6 测试

方法二SqlSessionDaoSupport

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
    public List<User> selectUser() {

        return getSqlSession().getMapper(UserMapper.class).selectUser();
    }
}

  

调用SqlSessionDaoSupport中getSqlSession()方法会获得SqlSessionTemplate
13 声明式事物
sql语句
开启事务
start transaction 或者 begin
(业务)
提交事务commit
回滚 rolllback
1事物的特性
  把一组事务当成一个业务来做:要么都成功,要么都失败
  事务在项目的开发中,很重要,涉及数据的一致性问题
  确保完整性和一致性
事务的ACID原则
Atomicity 原子性
  事务是不可分割的最小单位,要末同时成功,要摸同时失败
Consistency一致性
   事务完成时,必须使所有的数据保持一致的状态
Isolation 隔离型
  多个事务操作的可见性 多个业务操作同一个资源,不会相互干扰防止数据的损坏
Durability 持久型
  
事务一旦操作成功或者回滚,它对数据库中数据的改变就是永久的


为什么需要事务


   如果不配置事务,可能数据提交不一致的情况


   若果我们不在Spring配置声明式事务,我们就需要在代码中手动配置事务


  事务在项目开发中十分的重要,设计到数据的一致性和完整性


 //不配置事务的传播性,代码运行失败(解释 在一个方法中先增加一个数据,在删除它 ,可是删除数据代码不能执行,但是增加已经执行,这就导致即使程序没有运行,数据也被添加了进去),事务也会执行。

//保证代码运行失败,事务不会执行需要配置事务的传播性。和事务的切入点;

 

<tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--你要给哪些方法配置事务-->
        <!--配置事务的传播特性    propagation 传播-->
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED"/>
            <tx:method name="add" propagation="REQUIRED"/>
            <tx:method name="delete" propagation="REQUIRED"/>
            <tx:method name="update" propagation="REQUIRED"/>
            <tx:method name="query" read-only="true"/>
        </tx:attributes>
    </tx:advice>
    <!--配置事务的切入-->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* com.yang.mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>

 

 

 

 

 

 

 

 

 

 

 

 


















 

posted @ 2021-10-07 21:58  互联.王  阅读(309)  评论(0编辑  收藏  举报