Spring5笔记

Spring5框架

1.Spring概念

*Spring是轻量化的开源的JavaEE框架	
*Spring可以解决企业开发的复杂性
*Spring有两个核心部分:IOC和AOP
	1.IOC:控制反转,把创建对象过程交给Spring进行管理
	2.AOP:面向切面,不修改源代码进行功能增强
*Spring框架的特点:
	1.方便解耦,简化开发
	2.AOP编程的支持
	3.方便程序测试
	4.方便整合各种优秀框架
	5.降低JavaeeAPI的使用难度
	6.方便进行事务操作
Spring的入门案例
1.创建普通类,在这个类创建普通方法(导入Spring jar包)
public class User {
    public void add(){
        System.out.println("Hello Spring");
    }
}

2.创建 Spring 配置文件,在配置文件配置创建的对象 
  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 http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--配置user对象创建-->
    <bean id="user" class="com.Le.User"></bean>
</beans>
3.进行测试代码编写
public class TestSpring5 {
    @Test
    public void testAdd(){
        //加载Spring配置文件
        ApplicationContext Context = new ClassPathXmlApplicationContext("bean.xml");
        //获取配置创建的对象
        User user = Context.getBean("user", User.class);
        System.out.println(user);
        user.add();

    }
}

2.IOC容器

*IOC底层原理
*IOC接口(BeanFactory)
*IOC操作Bean管理(基于XML)
*IOC操作Bean管理(基于注解)
什么是IOC
	1.控制反转,把对象创建和对象之间的调用过程,交给Sping处理
	2.使用IOC的目的,为了耦合度更低
	3.开头做的入门案例就是IOC实现
IOC底层原理
	1.XML解析,工厂模式,反射
	IOC思想基于IOC容器完成,IOC底层容器就是对象工厂
	
	*Spring 提供 IOC 容器实现两种方式:(两个接口)
		BeanFactory:IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用 
			*加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
		ApplicationContext:BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人员进行使用
			*加载配置文件时候就会把在配置文件对象进行创建
	*ApplicationContext接口有两个实现类

FileSystemXmlApplicationContext:类在磁盘中的路径
ClassPathXmlApplicationContext:类在项目中的路径
IOC操作Bean管理(概念)
Bean管理是指两个操作
	Spring创建对象
	Spring注入属性
Bean管理操作有两种
	基于XML配置文件方式实现
	基于注解方式实现
	1.基于XML方式创建对象
		*在Spring配置文件中,使用bean标签,标签里面添加对应的属性,就可以实现对象的创建
		*在bean标签有很多属性,介绍常用的属性
			id属性:唯一表示
			class属性:类全路径(包类路径)
	*创建对象时,默认执行无参构造方法完成对象创建
	2.基于XMl方式注入属性
		*DI:依赖注入,就是注入属性
		第一种注入方式:使用set方法进行注入
			创建类,定义属性和相应的Set方法
		第二种注入方式:使用参数构造进行注入
		    在spring 配置文件配置对象创建,配置属性注入
<!--set方法注入属性-->
    <bean id="book" class="com.Le.Book">
        <!--使用properties完成属性注入-->
        <property name="bname" value="三国演义"></property>
        <property name="bauthor" value="罗贯中"></property>
    </bean>
p名称空间注入:
 *使用p名称空间注入,可以简化基于XML的配置方式
 1.添加p名称空间在配置文件中
<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
2.进行属性注入,在 bean 标签里面进行操作(set方法注入属性)
<bean id="book" class="com.atguigu.spring5.Book" p:bname="九阳神功" 
p:bauthor="无名氏"></bean>
1.字面量null值
<property name="bauthor">
           <null></null>
       </property>
2.属性包含特殊字符
<!--属性值包含特殊符号
1 把<>进行转义 &lt; &gt;
2 把带特殊符号内容写到 CDATA
-->
<property name="address">
<value><![CDATA[<<南京>>]]></value>
</property>
注入属性-外部bean
1.创建两个类Service类和Dao类
2.在Service中调用Dao的方法
3.在Spring文件中进行配置
public class Service {
    public UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    public void add(){
        System.out.println("Service add......");
        userDao.update();
    }
}

public class UserDaoImp implements UserDao{
    @Override
    public void update() {
        System.out.println("UserDao..");
    }
}
<bean id="Service" class="com.Le.Service.Service">
        <property name="userDao" ref="UserDao"></property>
    </bean>

    <bean id="UserDao" class="com.Le.Dao.UserDaoImp"></bean>
注入属性-内部bean
1.一对多关系:部门和员工一个部门有多个员工,一个员工属于一个部门,部门是一,员工是多
2.在实体类之间表示一对多关系,员工表示所属部门,使用对象属性进行表示 
//员工类
public class Emp {
    private String ename;
    private String gender;
    //员工属于某一部门,使用对象形式表示
    private Dept dept;

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public void eprint(){
        System.out.println(ename+"\n"+gender+"\n"+dept);
    }

}
//部门类
public class Dept {
    private String dname;

    public void setDname(String dname) {
        this.dname = dname;
    }

//    toString方法遇到print是会自动显示(调用)
    @Override
    public String toString() {
        return "Dept{" +
                "dname='" + dname + '\'' +
                '}';
    }
}
 <!--内部bean写法-->
    <bean id="emp" class="com.Le.bean.Emp">
        <property name="ename" value="Ale"></property>
        <property name="gender" value="Gao san"></property>
        <!--设置对象类型属性-->
        <property name="dept">
            <bean id="dept" class="com.Le.bean.Dept">
                <property name="dname" value="Yan"></property>
            </bean>
        </property>
    </bean>
IOC 操作 Bean 管理(xml 注入集合属性)
1.注入数组类型属性
2.注入list集合属性
3.注入map集合属性
public class stu {
    //1,数组类型属性
    private String[] course;
    //2,List集合类型属性
    private List<String> list;
    //3,map集合类型属性
    private Map<String,String> map;


    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setCourse(String[] course) {
        this.course = course;
    }

    public void print_Test(){
        System.out.println(Arrays.toString(course) +"\n"+list+"\n"+map);
    }

}
<bean name="stu" class="com.Le.collectiontype.stu">
        <property name="course">
            <array>
                <value>java</value>
                <value>mysql</value>
            </array>
        </property>
        <property name="list">
            <list>
                <value>Ale</value>
                <value>YanYan</value>
            </list>
        </property>
        <property name="map">
            <map>
                <entry key="Liu" value="Le"></entry>
                <entry key="Yan" value="Yan"></entry>
            </map>
        </property>
    </bean>
两种bean(普通bean和工厂bean)
*Spring有两种类型bean,一种是普通类型的bean,一种是工厂bean
	*普通bean,在配置文件中,bean类型就是返回类型
	*工厂bean,配置文件中,定义bean类型可以和返回的类型不一样
		1.创建类,让这个类作为工厂 bean,实现接口 FactoryBean
		2.实现接口里面的方法,在实现的方法中定义返回的 bean 类型
public class Mybean implements FactoryBean<Course> {
    /**
     * 定义返回bean
      * @return
     * @throws Exception
     */
    @Override
    public Course getObject() throws Exception {
        Course course = new Course();
        course.setCourse("abc");
        return course ;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}
<bean id="mybean" class="com.Le.factorybean.Mybean"></bean>
bean作用域
*在Spring中,设置bean实例是单实例还是多实例
*在Spring里面,默认情况下,bean是实例对象

*在Spring配置文件bean标签中有属性(scope)用于设置单实例还是多实例
*scope属性值
	1.默认值,singleton,表示是单实例对象
	2.prototype,表示是多实例对象
*singleton和prototype的区别
	1.singleton是单实例,prototype是多实例
	2.设置scope值为singleton时,是加载spring配置文件时就会创建对象
	  设置scpoe值为prototype时,不是在加载spring配置文件时创建对象,而是在调用getBean()方法时调用对象.
bean生命周期
*生命周期
1.通过构造器创建 bean 实例(无参数构造)
2.为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
3.调用 bean 的初始化的方法(需要进行配置初始化的方法)
4.bean 可以使用了(对象获取到了)
5.当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
public class Order {
    private String name;

    public Order() {
        System.out.println("第一步,执行构造方法创建bean实例");
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("第二步,执行set方法设置属性");
    }
    public void init_Method(){
        System.out.println("第三步,执行初始化方法");
    }
    public void destroy_Method(){
        System.out.println("第五步,执行销毁方法");
    }

    @Override
    public String toString() {
        return "Order{" +
                "name='" + name + '\'' +
                '}';
    }
}
<bean id="bean" class="com.Le.bean.Order" init-method="init_Method" destroy-method="destroy_Method">
        <property name="name" value="iphone"></property>
    </bean>
@Test
    public void test_bean(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
        Order bean = context.getBean("bean", Order.class);
        System.out.println("第四步,创建bean实例对象");
        System.out.println(bean);

        context.close();
    }

在这里插入图片描述

*生命周期
1.通过构造器创建 bean 实例(无参数构造)
2.为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
3.把bean实例传递bean后置处理器的方法
4.调用 bean 的初始化的方法(需要进行配置初始化的方法)
5.把bean实例传递给bean后置处理器的方法
6.bean 可以使用了(对象获取到了)
7.当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
//创建类,实现接口 BeanPostProcessor,创建后置处理器
public class MyBeanPost implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化前执行方法");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化后执行方法");
        return bean;
    }
}
<bean id="bean" class="com.Le.bean.Order" init-method="init_Method" destroy-method="destroy_Method">
        <property name="name" value="iphone"></property>
    </bean>
    <bean id="MyBeanPost" class="com.Le.bean.MyBeanPost"></bean>

在这里插入图片描述

XML自动装配
*什么是自动装配
	根据指定自动装配规则(属性名称或者属性类型),Spring将自动匹配的属性值进行注入
*自动装配过程
	1.根据属性名称自动注入
<!--实现自动装配
 bean 标签属性 autowire,配置自动装配
 autowire 属性常用两个值:
 byName 根据属性名称注入 ,注入值 bean 的 id 值和类属性名称一样
 byType 根据属性类型注入
-->
<bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byName">
 <!--<property name="dept" ref="dept"></property>-->
</bean>
<bean id="dept" class="com.atguigu.spring5.autowire.Dept"></bean>
	2.根据属性类型进行自动注入
<!--实现自动装配
 bean 标签属性 autowire,配置自动装配
 autowire 属性常用两个值:
 byName 根据属性名称注入 ,注入值 bean 的 id 值和类属性名称一样
 byType 根据属性类型注入
-->
<bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byType">
 <!--<property name="dept" ref="dept"></property>-->
</bean>
<bean id="dept" class="com.atguigu.spring5.autowire.Dept"></bean>
外部属性文件
<!--引入context名称空间-->
<?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">

    <!--直接配置连接池-->
<!--    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">-->
<!--        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>-->
<!--        <property name="url"-->
<!--                  value="jdbc:mysql://localhost:3306/jdbc"></property>-->
<!--        <property name="username" value="root"></property>-->
<!--        <property name="password" value="745210"></property>-->
<!--    </bean>-->

    <!--引入外部属性标签-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${driverClassName}"></property>
        <property name="url"
                  value="${url}"></property>
        <property name="username" value="${username}"></property>
        <property name="password" value="${password
        }"></property>
    </bean>

</beans>
基于注解方式实现对象创建
*什么是注解
	1.注解是代码特殊标记,格式:@注解名称(属性名称=属性值, 属性名称=属性值..)
	2.使用注解,注解作用在类上面,方法上面,属性上面
	3.使用注解目的:简化 xml 配置
*Spring 针对 Bean 管理中创建对象提供注解
	1.@Component
	2.@Service
	3.@Controller
	4.@Repository
	上面四个注解功能是一样的,都可以用来创建 bean 实例

*基于注解方式实现对象创建
	1.引入依赖

在这里插入图片描述

	2.开启组件扫描
<!--开启组件扫描
 1 如果扫描多个包,多个包使用逗号隔开
 2 扫描包上层目录
-->
<context:component-scan base-package="com.atguigu"></context:component-scan>
	3.创建类,在类上面添加创建对象注解
//在注解里面 value 属性值可以省略不写,
//默认值是类名称,首字母小写
//UserService -- userService
@Component(value = "userService") //<bean id="userService" class=".."/>
public class UserService {
 public void print(){
        System.out.println("This is an annotated test method");
    }
}
//Test
public class Test_Annotated {
    @Test
    public void print(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        UserService userService = context.getBean("userService", UserService.class);
        userService.print();
    }
}
*开启组件扫描细节配置
<!--示例 1
 use-default-filters="false" 表示现在不使用默认 filter,自己配置 filter
 context:include-filter ,设置扫描哪些内容
-->
<context:component-scan base-package="com.Le" use-defaultfilters="false">
 <context:include-filter type="annotation" 
 
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--示例 2
 下面配置扫描包所有内容
 context:exclude-filter: 设置哪些内容不进行扫描
-->
<context:component-scan base-package="com.Le">
 <context:exclude-filter type="annotation" 
 
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
基于注解方式实现属性注入
*@Autowired:根据属性类型进行自动装配
*@Qualifier:根据名称进行自动注入
*@Resource:可以根据类型和名称进行自动注入(为javax包中)
*@Value:普通注入,直接注入属性值
	1.把 service 和 dao 对象创建,在 service 和 dao 类添加创建对象注解
 	2.在 service 注入 dao 对象,在 service 类添加 dao 类型属性,在属性上面使用注解
public interface UserDao {
    public void print();
}
@Repository(value = "UserDao")
public class UserDaoImp implements UserDao{

    @Override
    public void print() {
        System.out.println("This is a test method for attribute injection based on annotation");
    }
}
@Service
public class UserService {
//    @Autowired
//    @Qualifier(vlaue = "UserDao")
//	  @Resource
//	  @Resource(name = "UserDao")
    private UserDao userDao;
    
	@Value(value = "Le")
	private String name;
	
    public void print(){
    	System.out.println(name);
        System.out.println("This is an annotated test method");
        userDao.print();
    }
}
完全注解开发
*创建配置类,代替XML文件
/**
 * @author Kirito
 * @Configuration:作为配置类,代替XML文件
 * @ComponentScan:<context:component-scan base-package="com.Le"></context:component-scan>
 */
@Configuration
@ComponentScan(basePackages = {"com.Le"})
public class SpringConfig {

}
//测试类
public class Test_WithoutXML {
    @Test
    public void print(){
        //加载配置类
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserService userService = context.getBean("userService", UserService.class);
        userService.print();
    }
}

3.AOP

什么是 AOP
1.面向切面编程(方面),利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得
业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
2.通俗描述:不通过修改源代码方式,在主干功能里面添加新功能
3.使用登录例子说明 AOP

在这里插入图片描述

AOP底层原理
*AOP底层使用动态代理
1.有接口情况:使用JDK动态代理

在这里插入图片描述

2.没有接口情况:使用CGLIB动态代理

在这里插入图片描述

JDK动态代理
* 使用 JDK 动态代理,使用 Proxy 类里面的方法创建代理对象
	1.调用newProxyInstance方法

在这里插入图片描述

*方法有三个参数
	第一参数,类加载器
	第二参数,增强方法所在的类,这个类实现的接口,支持多个接口
	第三参数,实现这个接口 InvocationHandler,创建代理对象,写增强的部分
public interface UserDao {

    public int add (int a,int b);

    public String update(String a,String b);
}

public class UserDaoImp implements UserDao{
    @Override
    public int add(int a, int b) {
        System.out.println("add is running");
        return a+b;
    }

    @Override
    public String update(String a, String b) {
        return a+b;
    }

    @Override
    public String toString() {
        return "UserDaoImp{}";
    }
}
public class JDKProxy {
    public static void main(String[] args) {
		//创建接口实现代理对象
        Class[] interfaces = {UserDao.class};
        //创建需要增加的类
        UserDaoImp userDaoImp = new UserDaoImp();
        //接收代理类
        //       通过实现匿名内部类方式 
//        UserDao userDao =(UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
//            @Override
//            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                return null;
//            }
//        });
        UserDao userDao =(UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoImpProxy(userDaoImp));
		//调用方法
        userDao.add(1,2);
    }


}
//创建代理对象
class UserDaoImpProxy implements InvocationHandler {

	//创建Object对象用于接收需要增强的类
    private Object object;
    //有参构造,接收类
    public UserDaoImpProxy(Object object){
        this.object = object;
    }
	//被增强的逻辑
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //方法之前
        System.out.println("方法之前执行:"+method.getName()+"传递的参数:"+ Arrays.toString(args));
        //被增强的方法执行
        Object res = method.invoke(object, args);
        //方法之后
        System.out.println("方法之后执行:"+object);
        return res;

    }
}

在这里插入图片描述

AOP(术语)
*连接点
	类里面哪些方法可以被增强,这些方法称为连接点
*切入点
	实际上被增强的方法,称为切入点
*通知(增强)
	实际增强的逻辑部分称为通知(增强)
	*通知有多种类型
		前置通知
		后置通知
		环绕通知
		异常通知
		最终通知
*切面
	是动作,把通知应用到切入点的过程
AOP操作(准备工作)
*Spring 框架一般都是基于 AspectJ 实现 AOP 操作
	AspectJ 不是 Spring 组成部分,独立 AOP 框架,一般把 AspectJ 和 Spirng 框架一起使用,进行 AOP 操作
*基于 AspectJ 实现 AOP 操作
	基于 xml 配置文件实现
	基于注解方式实现(使用)
*在项目中引入AOP相关依赖

在这里插入图片描述

*切入点表达式
(1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强
(2)语法结构: execution([权限修饰符] [返回类型] [类全路径] [方法名称]([参数列表]) )
举例 1:对 com.Le.dao.BookDao 类里面的 add 进行增强
	execution(* com.Le.dao.BookDao.add(..))
举例 2:对 com.Le.dao.BookDao 类里面的所有的方法进行增强
	execution(* com.Le.dao.BookDao.* (..))
举例 3:对 com.Le.dao 包里面所有类,类里面所有方法进行增强
	execution(* com.Le.dao.*.* (..))
AspectJ注解
*创建类,在类里面定义方法
@Component
public class User {
    public void add(){
        int a = 0;
        int b = 1;
        System.out.println(a/b);
    }
}

*创建增强类,编写增强逻辑
//增强的类
@Component
@Aspect
public class UserProxy {

    //前置通知

    @Before(value = "execution(* com.Le.spring5.AopAnno.User.add(..))")
    public void before(){
        System.out.println("before...");
    } 
 }
*进行通知的配置
<?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">
        <!--开启注解扫描-->
        <context:component-scan base-package="com.Le.spring5.AopAnno"></context:component-scan>
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
*配置不同类型的通知
//增强的类
@Component
@Aspect
public class UserProxy {

    //前置通知

    @Before(value = "execution(* com.Le.spring5.AopAnno.User.add(..))")
    public void before(){
        System.out.println("before...");
    }

    //后置通知

    @AfterReturning(value = "execution(* com.Le.spring5.AopAnno.User.add(..))")
    public void AfterReturning(){
        System.out.println("AfterReturning");
    }

    //最终通知

    @After(value = "execution(* com.Le.spring5.AopAnno.User.add(..))")
    public void After(){
        System.out.println("After");
    }

    //异常通知

    @AfterThrowing(value = "execution(* com.Le.spring5.AopAnno.User.add(..))")
    public void AfterThrowing(){
        System.out.println("AfterThrowing");
    }

    //环绕通知

    @Around(value = "execution(* com.Le.spring5.AopAnno.User.add(..))")
    public void Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        System.out.println("环绕之前");
        proceedingJoinPoint.proceed();
        System.out.println("环绕之后");
    }

}

//Test
/**
 * @author Kirito
 */
public class UserTest {
    @Test
    public void testUser(){
        ApplicationContext context
                = new ClassPathXmlApplicationContext("bean1.xml");
        User user = context.getBean("user", User.class);
        user.add();
    }

}

在这里插入图片描述

*相同切入点的抽取
//相同切入点的抽取

    @Pointcut(value = "execution(* com.Le.spring5.AopAnno.User.add(..))")
    public void pointCut(){}
    
    //前置通知

    @Before(value = "pointCut()")
    public void before(){
        System.out.println("before...");
*有多个增强类多同一个方法进行增强,设置增强类优先级
在增强类上面添加注解 @Order(数字类型值),数字类型值越小优先级越高
@Component
@Aspect
@Order(1)
public class PersonProxy
*完全注解开发
@Configuration
@ComponentScan(basePackages = "com.Le.spring5.AopAnno")
@EnableAspectJAutoProxy
public class Configuration_User {

}
//Test
public class UserTest {
    @Test
    public void testUser(){
        ApplicationContext context
                = new AnnotationConfigApplicationContext(Configuration_User.class);
        User user = context.getBean("user", User.class);
        user.add();
    }

}
AspectJ 配置文件
*创建两个类,增强类和被增强类
public class User {
    public void add(){
        System.out.println("add");}
}

public class UserProxy {

    public void before(){
        System.out.println("before");
    }
}

*配置AspectJ配置文件
<?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 id="User" class="com.Le.spring5.AopXMl.User"></bean>
    <bean id="UserProxy" class="com.Le.spring5.AopXMl.UserProxy"></bean>
    <aop:config>
        <!--切入点-->
        <aop:pointcut id="p" expression="execution(* com.Le.spring5.AopXMl.User.add(..))"/>

        <!--切面-->
        <aop:aspect ref="UserProxy">
            <!--增强作用在具体的方法上-->
            <aop:before method="before" pointcut-ref="p"></aop:before>
        </aop:aspect>

    </aop:config>
</beans>
*编写测试方法
  @Test
    public void test_User(){
        ApplicationContext context
                = new ClassPathXmlApplicationContext("bean2.xml");
        User user = context.getBean("User", User.class);
        user.add();
    }

在这里插入图片描述

4.JdbcTemple

什么是JdbcTemple(概念)
*Spring框架对JDBC进行封装,使用JdbcTemple方便实现对数据库的操作

*准备工作

在这里插入图片描述

*在Spring配置文件中配置数据库连接池
 <!--直接配置连接池-->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
            <property name="url"
                      value="jdbc:mysql://localhost:3306/jdbc"></property>
            <property name="username" value="root"></property>
            <property name="password" value="745210"></property>
        </bean>
*配置Jdbc对象,注入DataSource
<!--配置JdbcTemple对象-->
    <bean id="jdbcTemple" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
*创建Service类,创建Dao类,在Dao类中注入JdbcTemple对象
public class BookDaoImp implements BookDao{
    @Autowired
    private JdbcTemplate jdbcTemplate;
}
@Service
public class BookService {
    @Autowired
    private BookDao bookDao;
}

JdbcTemple(添加,修改,删除,显示)
*利用数据库表创建实体类
public class Book {
    private int userId;
    private String userName;
    private String usStatus;

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public void setUsStatus(String usStatus) {
        this.usStatus = usStatus;
    }

    public int getUserId() {
        return userId;
    }

    public String getUserName() {
        return userName;
    }

    public String getUsStatus() {
        return usStatus;
    }
}
*编写 service 和 dao
	在 dao 进行数据库添加操作
	调用 JdbcTemplate 对象里面 update 方法实现添加操作
@Repository
public class BookDaoImp implements BookDao{

    @Autowired
    private JdbcTemplate jdbcTemplate;


    @Override
    public void add(Book book) {
        String sql = "insert into t_book values(?,?,?)";

        Object[] args = {book.getUserId(), book.getUserName(),
                book.getUsStatus()};

        int update = jdbcTemplate.update(sql,args);

        System.out.println(update);
    }
}
*测试
public class TestBookServe {
    @Test
    public void testBookServe(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        BookService bookService = context.getBean("bookService", BookService.class);
        Book book = new Book();
        book.setUserId(1);
        book.setUserName("Le");
        book.setUsStatus("Liu");
        bookService.addBook(book);
    }
}
//修改
@Override
public void updateBook(Book book) {
 String sql = "update t_book set username=?,ustatus=? where user_id=?";
 Object[] args = {book.getUsername(), book.getUstatus(),book.getUserId()};
 int update = jdbcTemplate.update(sql, args);
 System.out.println(update);
}
//删除
@Override
public void delete(String id) {
 String sql = "delete from t_book where user_id=?";
 int update = jdbcTemplate.update(sql, id);
 System.out.println(update);
}
*查询返回对象
@Override
    public Book selectBook(String id) {

        String sql = "select * from t_book where userId=?";

       Book book =  jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<Book>(Book.class),id);

       return book;
    }
*查询返回集合
@Override
    public List<Book> selectBook() {
        String sql = "select * from t_book";

        List<Book> books =  jdbcTemplate.query(sql,new BeanPropertyRowMapper<Book>(Book.class));

        return books;
    }
*批量增加功能
@Override
    public void batchAddBook(List<Object[]> batchArgs) {
        String sql = "insert into t_book values(?,?,?)";
        int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
        System.out.println(Arrays.toString(ints));
    }
*批量修改
Override
public void batchUpdateBook(List<Object[]> batchArgs) {
 String sql = "update t_book set username=?,ustatus=? where user_id=?";
 int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
 System.out.println(Arrays.toString(ints));
}
//批量修改
@Override
public void batchUpdateBook(List<Object[]> batchArgs) {
 String sql = "update t_book set username=?,ustatus=? where user_id=?";
 int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
 System.out.println(Arrays.toString(ints));
}
//批量修改
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {"1","java01","a3"};
Object[] o2 = {"2","c++1010","b4"};
Object[] o3 = {"3"","MySQL1111","c5"};
batchArgs.add(o1);
batchArgs.add(o2);
batchArgs.add(o3);
//调用方法实现批量修改
bookService.batchUpdate(batchArgs);
*批量删除
//批量删除
@Override
public void batchDeleteBook(List<Object[]> batchArgs) {
 String sql = "delete from t_book where user_id=?";
 int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
 System.out.println(Arrays.toString(ints));
}
//批量删除
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {"3"};
Object[] o2 = {"4"};
batchArgs.add(o1);
batchArgs.add(o2);
//调用方法实现批量删除
bookService.batchDelete(batchArgs);

5.事务管理

什么是事务
(1)事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操
作都失败
(2)典型场景:银行转账
* lucy 转账 100 元 给 mary
* lucy 少 100,mary 多 100
2、事务四个特性(ACID)
(1)原子性
(2)一致性
(3)隔离性
(4)持久性
搭建事务操作与环境

在这里插入图片描述

public interface UserDao {
    public void addMoney();
    public void reduceMoney();
}

@Repository
public class UserDaoImp implements UserDao{

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void addMoney(){
        String sql = "update t_account set money=money-? where username=?";
        jdbcTemplate.update(sql,100,"Kirito");
    }
    @Override
    public void reduceMoney(){
        String sql = "update t_account set money=money+? where username=?";
        jdbcTemplate.update(sql,100,"Asuna");
    }

}
@Service
public class UserService {

    @Autowired
    private UserDao userDao;
    //转账的方法
    public void accountMoney() {
        //Asuna 少 100
        userDao.reduceMoney();
        //Kirito 多 100
        userDao.addMoney();
    }
}
//Test
public class TestBookServe {

    @Test
    public void testUserService(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        UserService userService = context.getBean("userService", UserService.class);
        userService.accountMoney();
    }

}
上面代码,如果正常执行没有问题的,但是如果代码执行过程中出现异常,有问题
使用事务解决

事务操作过程
try{
            //1,开启事务

            //2,进行业务操作
            //Asuna 少 100
            userDao.reduceMoney();

            //模拟异常
            int i = 1/0;
            //Kirito 多 100
            userDao.addMoney();

            //3,没有异常提交事务
        }catch (Exception e){
            //出现异常,事务回滚
        }
事务操作(Spring 事务管理介绍)
1、事务添加到 JavaEE 三层结构里面 Service 层(业务逻辑层)
2、在 Spring 进行事务管理操作
(1)有两种方式:编程式事务管理和声明式事务管理(使用)
3、声明式事务管理
(1)基于注解方式(使用)
(2)基于 xml 配置文件方式
4、在 Spring 进行声明式事务管理,底层使用 AOP 原理
5、Spring 事务管理 API

在这里插入图片描述

注解声明式事务管理器
1、在 spring 配置文件配置事务管理器
<!--创建事务管理器-->
<bean id="transactionManager" 
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 <!--注入数据源-->
 <property name="dataSource" ref="dataSource"></property>
</bean>
2、在 spring 配置文件,开启事务注解
(1)在 spring 配置文件引入名称空间 tx
<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" 
 xmlns:tx="http://www.springframework.org/schema/tx" 
 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 
 					http://www.springframework.org/schema/tx 
					http://www.springframework.org/schema/tx/spring-tx.xsd">
(2)开启事务注解
<!--开启事务注解-->
<tx:annotation-driven transactionmanager="transactionManager"></tx:annotation-driven>
3、在 service 类上面(或者 service 类里面方法上面)添加事务注解
(1)@Transactional,这个注解添加到类上面,也可以添加方法上面
(2)如果把这个注解添加类上面,这个类里面所有的方法都添加事务
(3)如果把这个注解添加方法上面,为这个方法添加事务
@Service
@Transactional
public class UserService {
声明式事务管理参数配置
1、在 service 类上面添加注解@Transactional,在这个注解里面可以配置事务相关参数
2、propagation:事务传播行为
(1)多事务方法直接进行调用,这个过程中事务 是如何进行管理的

在这里插入图片描述

3、ioslation:事务隔离级别
(1)事务有特性成为隔离性,多事务操作之间不会产生影响。不考虑隔离性产生很多问题
(2)有三个读问题:脏读、不可重复读、虚(幻)读
(3)脏读:一个未提交事务读取到另一个未提交事务的数据
(4)不可重复读:一个未提交事务读取到另一提交事务修改数据
(5)虚读:一个未提交事务读取到另一提交事务添加数据
(6)解决:通过设置事务隔离级别,解决读问题
4、timeout:超时时间
(1)事务需要在一定时间内进行提交,如果不提交进行回滚
(2)默认值是 -1 ,设置时间以秒单位进行计算
5、readOnly:是否只读
(1)读:查询操作,写:添加修改删除操作
(2)readOnly 默认值 false,表示可以查询,可以添加修改删除操作
(3)设置 readOnly 值是 true,设置成 true 之后,只能查询
6、rollbackFor:回滚
(1)设置出现哪些异常进行事务回滚
7、noRollbackFor:不回滚
(1)设置出现哪些异常不进行事务回滚
XML声明式事务管理

6.Spring5新特性

1、整个 Spring5 框架的代码基于 Java8,运行时兼容 JDK9,许多不建议使用的类和方
法在代码库中删除
2、Spring 5.0 框架自带了通用的日志封装 
(1)Spring5 已经移除 Log4jConfigListener,官方建议使用 Log4j2
(2)Spring5 框架整合 Log4j2
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > 
ALL -->
<!--Configuration 后面的 status 用于设置 log4j2 自身内部的信息输出,可以不设置,
当设置成 trace 时,可以看到 log4j2 内部各种详细输出-->
<configuration status="INFO">
 <!--先定义所有的 appender-->
 <appenders>
 <!--输出日志信息到控制台-->
 <console name="Console" target="SYSTEM_OUT">
 <!--控制日志输出的格式-->
 <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-
5level %logger{36} - %msg%n"/>
 </console>
 </appenders>
 <!--然后定义 logger,只有定义 logger 并引入的 appender,appender 才会生效-->
 <!--root:用于指定项目的根日志,如果没有单独指定 Logger,则会使用 root 作为
默认的日志输出-->
 <loggers>
 <root level="info">
 <appender-ref ref="Console"/>
 </root>
 </loggers>
</configuration>
Spring5 框架核心容器支持@Nullable 注解
(1)@Nullable 注解可以使用在方法上面,属性上面,参数上面,表示方法返回可以为空,属性值可以
为空,参数值可以为空
(2)注解用在方法上面,方法返回值可以为空
(3)注解使用在方法参数里面,方法参数可以为空
(4)注解使用在属性上面,属性值可以为空
4、Spring5 核心容器支持函数式风格 GenericApplicationContext
//函数式风格创建对象,交给 spring 进行管理
@Test
public void testGenericApplicationContext() {
 //1 创建 GenericApplicationContext 对象
 GenericApplicationContext context = new GenericApplicationContext();
 //2 调用 context 的方法对象注册
 context.refresh();
 context.registerBean("user1",User.class,() -> new User());
 //3 获取在 spring 注册的对象
 // User user = (User)context.getBean("com.atguigu.spring5.test.User");
 User user = (User)context.getBean("user1");
 System.out.println(user);
}
(1)整合 JUnit4
第一步 引入 Spring 相关针对测试依赖
第二步 创建测试类,使用注解方式完成
@RunWith(SpringJUnit4ClassRunner.class) //单元测试框架
@ContextConfiguration("classpath:bean1.xml") //加载配置文件
public class JTest4 {
 @Autowired
 private UserService userService;
 @Test
 public void test1() {
 userService.accountMoney();
 }
}
(2)Spring5 整合 JUnit5
第一步 引入 JUnit5 的 jar 包
第二步 创建测试类,使用注解完成
@ExtendWith(SpringExtension.class)
@ContextConfiguration("classpath:bean1.xml")
public class JTest5 {
 @Autowired
 private UserService userService;
 @Test
 public void test1() {
 userService.accountMoney();
 }
}
(3)使用一个复合注解替代上面两个注解完成整合
@SpringJUnitConfig(locations = "classpath:bean1.xml")
public class JTest5 {
 @Autowired
 private UserService userService;
 @Test
 public void test1() {
 userService.accountMoney();
 }
}
1、SpringWebflux 介绍
(1)是 Spring5 添加新的模块,用于 web 开发的,功能和 SpringMVC 类似的,Webflux 使用
当前一种比较流程响应式编程出现的框架。

在这里插入图片描述

(2)使用传统 web 框架,比如 SpringMVC,这些基于 Servlet 容器,Webflux 是一种异步非阻
塞的框架,异步非阻塞的框架在 Servlet3.1 以后才支持,核心是基于 Reactor 的相关 API 实现
的。
(3)解释什么是异步非阻塞
* 异步和同步
* 非阻塞和阻塞
** 上面都是针对对象不一样
** 异步和同步针对调用者,调用者发送请求,如果等着对方回应之后才去做其他事情就是同
步,如果发送请求之后不等着对方回应就去做其他事情就是异步
** 阻塞和非阻塞针对被调用者,被调用者受到请求之后,做完请求任务之后才给出反馈就是阻
塞,受到请求之后马上给出反馈然后再去做事情就是非阻塞
(4)Webflux 特点:
第一 非阻塞式:在有限资源下,提高系统吞吐量和伸缩性,以 Reactor 为基础实现响应式编程
第二 函数式编程:Spring5 框架基于 java8,Webflux 使用 Java8 函数式编程方式实现路由请求
(5)比较 SpringMVC

在这里插入图片描述

第一 两个框架都可以使用注解方式,都运行在 Tomet 等容器中
第二 SpringMVC 采用命令式编程,Webflux 采用异步响应式编程
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值