Spring

 学习资源

目录

IOC

IOC底层原理

IOC接口

 IOC操作bean管理

基于XML

基于XML方式创建对象​

 基于xml注入属性

 基于xml其他属性注入

xml自动装配

 注入外部属性文件​​

基于注解

开启组件扫描​

 组件扫描设置

基于注解属性注入

 泛型注入原理

完全注解开发

Bean作用域

 Bean生命周期

 FactoryBean

 IOC总结​

AOP

 AOP底层原理

  底层JDK动态代理

 AOP术语

AOP操作

引入AOP相关依赖

 切入点表达式

 基于注解方式实现

相同切入点抽取

增强类优先级 

基于xml配置文件

 SpEl

JdbcTemplate

 数据库配置​

事务

事务管理API

 基于注解方式声明事务

@Transactional相关参数

基于xml配置方式声明事务

 webflux



两个核心部分:

IOC:控制反转,把创建对象的过程交给Spring进行管理

Aop:面向切面,不修改源代码进行功能增强

IOC

1.控制反转,把对象创建和对象之间的调用过程,交给Spring管理

2.使用IOC目的:为了耦合度降低

IOC底层原理

xml解析、工厂模式、反射

IOC接口

1.IOC思想基于IOC容器完成,IOC容器底层就是对象工厂

2.Spring提供IOC容器实现两种方式:

(1)BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用——加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象

(2)ApplicationContext: BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用——加载配置文件时,就会把在配置文件对象进行创建

 IOC操作bean管理

Bean管理指的是两个操作:spring创建对象、spring注入属性

Bean管理操作两种方式:基于xml配置文件方式实现、基于注解方式实现。

基于XML

基于XML方式创建对象

 基于xml注入属性

 DI:依赖注入,就是注入属性

第一种注入方式:使用set方法进行注入

(1)创建类,定义属性和对应的set方法

(2)在spring配置文件配置对象创建,配置属性注入

第二种注入方式:使用有参数构造进行注入

(1)创建类,定义属性,创建属性对应有参构造方法

 (2)在spring配置文件中进行配置

 基于xml其他属性注入

1.字面量

(1)null值

 (2)属性值包含特殊符号

 2.注入属性外部bean

 3.注入属性内部bean

 4.级联赋值

5.注入集合属性

数组注入、List集合注入、Map集合注入

(1)创建类,定义数组,list,map,set类型属性,生成对应set方法

package com.study;

import java.util.List;
import java.util.Map;
import java.util.Set;

public class Stu {
    //数组类型属性
    private String[] courses;
    //list集合类型属性
    private List<String>  list;
    //set集合类型属性
    private Set<String> sets;
    //map集合类型属性
    private Map<String,String> map;
    public void setCourses(String[] courses) {
        this.courses = courses;
    }
    public void setList(List<String> list) {
        this.list = list;
    }
    public void setMap(Map<String, String> map) {
        this.map = map;
    }
    public void setSets(Set<String> sets) {
        this.sets = sets;
    }
    

}

(2)在spring配置文件进行配置

<?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">
    <bean id="stu" class="com.study.Stu">
        <!--        数组类型属性注入-->
        <property name="courses">
            <array>
                <value>java课程</value>
                <value>数据库课程</value>
            </array>
        </property>
        <!--        list类型属性注入-->
        <property name="list">
            <list>
                <value>张三</value>
                <value>小三</value>
            </list>
        </property>
        <!--        set类型属性注入-->
        <property name="sets">
            <set>
                <value>Mysql</value>
                <value>redis</value>
            </set>
        </property>
        <!--        map类型属性注入-->
        <property name="map>">
            <map>
                <entry key="JAVA" value="java"/>
                <entry key="PHP" value="php"/>
            </map>
        </property>
    </bean>

</beans>

6.在集合里设置对象类型值

    <bean>
    <property name="courseList">
            <list>
                <ref bean="course"></ref>
                <ref bean="course1"></ref>
            </list>
        </property>
    </bean>
    <!--    创建course对象-->
    <bean id="course" class="com.study.Course">
        <property name="name" value="spring框架"></property>
    </bean>
    <bean id="course1" class="com.study.Course">
        <property name="name" value="mybatis框架"></property>
    </bean>

xml自动装配

(1)根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入

 注入外部属性文件

基于注解

Spring针对Bean管理中创建对象提供注解,注:使用注解需要导入aop包,maven不需要,听说maven自动依赖

SpringSpringMVC
@Component普通 @Service业务层@Controller ”web层“ @Repository持久层

开启组件扫描

 组件扫描设置

<!--表示现在不使用filter,自己配置filter ,context:include-filter,设置扫描哪些内容-->
    <context:component-scan base-package="com.study"
                            use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>


<!--context:exclude-filter ,设置扫描哪些内容不进行扫描;-->
    <context:component-scan base-package="com.study">
<!--指定排除某个注解-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<!--指定排除某个具体的类-->
<context:exclude-filter type="assignable" expression="com.study.Book"/>
    </context:component-scan>

基于注解属性注入

@Autowired @Qualifier   @Resource@Value
根据属性类型进行自动装配根据属性名称进行装配可以根据类型或名称注入(jdk自带的)普通类型注入
 @Qualifier要和@Autowired一起使用

@Autowired自动装配的属性默认值是一定装配上的

@Autowired放在方法上,方法参数自动注入且方法在创建bean时执行

   @Value(value = "cc")
    private String name;
   @Autowired
   @Qualifier(value = "stu")
   private Stu stu;

spring中@Autowired注解失效的原因分析

spring中,类的成员变量如果使用了@Autowired,这个类必须交给Spring管理,否则注解失效.
原因: spring后置处理器解析此注解,对Bean做增强
交给Spring管理的方式:

  1)  xml中配置对应的Bean标签
  2)  @Component,@Service,@Controller,@Repository等
  3)  启动类或其他配置类,使用@Bean注解

2和3的区别:

  @Bean没有和类的定义绑定,通过方法返回对象,可以进行属性赋值,可以配置没有源码的第三方组件
  @Component系列是直接贴在类上的,与类的定义绑定在一起,组件扫描和自动装配更方便
注意: 需要最终引用类是交给Spring管理的,如果当前类B中@Autowired注入了类C,并通过@Component交给Spring管理,但类A在使用类B时,是new出来的,依然是无效的.

 泛型注入原理

 学习视频

完全注解开发

需要创建配置类   

@Configuration//作为配置类,替代xml配置文件
@ComponentScan(basePackages = {"com.study"})//开启扫描
public class Config {
}





@Test
public void annotion(){
//加载配置类,之前是加载xml文件
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        Course course = context.getBean("course", Course.class);
        System.out.println(course);
    }

Bean作用域

在Spring里面,设置创建bean实例是单例还是多例,默认情况下是单实例

设置单实例还是多实例

(1)在spring配置文件bean标签里面有属性用于设置

scope属性:{ prototype:多例;                 singleton:单例}

<!--单例-->
<bean id="course" class="com.study.Course" scope="singleton"></bean>
<!--多例-->
<bean id="course" class="com.study.Course" scope="prototype"></bean>

 Bean生命周期

从对象创建到销毁的过程  

 bea的后置处理器,生命周期七步

 实现  BeanPostProcessor

 FactoryBean

Spring有两种类型bean,一种普通bean,另外一种工厂bean(FactoryBean)

普通bean:在配置文件中定义bean类型就是返回类型

工厂bena:在配置文件定义bean类型可以返回类型不一样

第一步创建类,让这个类作为工厂bean,实现接口FactoryBean

第二步 实现接口里面的方法,在实现的方法中定义返回的bean类型

package com.Factorybean;

import com.study.Course;
import org.springframework.beans.factory.FactoryBean;

public class Mybean implements FactoryBean<Course> {
    //定义返回bean
    @Override
    public Course getObject() throws Exception {
        Course course = new Course();
        course.setName("abc");
        return course;
    }
    @Override
    public Class<?> getObjectType() {
        return null;
    }
}
<bean id="myBean" class="com.Factorybean.Mybean"></bean>
   @Test
    public void test() {
        ClassPathXmlApplicationContext context
                = new ClassPathXmlApplicationContext("bean1.xml");
        //配置文件类型是Mybean 这里返回Course类型
        Course course = context.getBean("myBean", Course.class);
        System.out.println(course);

    }

 IOC总结

AOP

不通过修改源代码方式,在主干功能里面添加新功能

 AOP底层原理

AOP底层使用动态代理,两种方式

第一种 有接口情况,使用JDK动态代理

第二种 没有接口情况,使用CGLIB动态代理 

  底层JDK动态代理

使用JDK动态代理,使用Proxy类里面的方法创建代理对象

 第一个参数:类加载器

第二个参数:增强方法所在的类,这个类实现的接口,支持多个接口

第三个参数:实现这个接口InvocationHandler,创建代理对象,要增强的部分

举例了解:

package com.study;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
interface UserDao {
    int add(int a,int b);

}
class UserDaoImpl implements UserDao{
    @Override
    public int add(int a, int b) {
        System.out.println("add执行");
        return a+b;
    }
}
class UserDaoProxy implements InvocationHandler {
    //把创建的是谁的代理对象,把谁传递过来
    //有参数构造传递
    private Object obj;
    public UserDaoProxy(Object obj){
        this.obj=obj;
    }
    //增强的逻辑
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //方法之前执行
        System.out.println("之前。。。"+method.getName()+"传递参数..."+ Arrays.toString(args));
        Object res = method.invoke(obj, args);
        //方法之后执行
        System.out.println("之后"+obj);
        return res;
    }
}
public class JDKProxy{
    public static void main(String[] args) {
        //创建接口实现类代理对象
        Class[] interfaces = {UserDao.class};
        //JDK代理
        UserDao dao =(UserDao)Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces,
                new UserDaoProxy(new UserDaoImpl()));
        int add = dao.add(1, 2);
        System.out.println(add);
    }
}

 AOP术语

1.连接点 :类里面哪些方法可以被增强,这些方法称为连接点

2.切入点 :实际被真正增强的方法,称为切入点

3.通知(增强):实际增强的逻辑部分称为通知(增强)有:

前置通知、后置通知、环绕通知、异常通知、最终通知

4.切面 :是动作,把通知应用到切入点的过程

AOP操作

Spring框架一般都是基于AspectJ实现AOP操作——AspectJ不是Spring组成部分,独立于AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作

两种操作方式:

基于xml配置文件实现

基于注解方式实现

引入AOP相关依赖

 切入点表达式

作用:知道对哪个类里面的哪个方法进行增强

语法结构:execution([权限修饰符][返回类型][类全路径][方法名称]([参数列表])

基于注解方式实现

开启注解扫描、开启Aspect生成代理对象

@Configuration//作为配置类,替代xml配置文件
@ComponentScan(basePackages = {"com.study"})//开启扫描
@EnableAspectJAutoProxy//开启Aspect生成代理对象
public class Config {
}

注解生成对象,增强类上面添加@Aspect

package com.study;

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

@Component
public class User {
    public void add(){
        System.out.println("add...");
    }
}
//增强类
@Component
@Aspect //生成代理对象
class UserProxy{
    //前置通知
    @Before(value = "execution(* com.study.User.add(..))")
    public void befor(){
        System.out.println("befer...");
    }
    //后置通知
    @AfterReturning(value = "execution(* com.study.User.add(..))")
    public void afterReturning(){
        System.out.println("afterReturning...");
    }
    //环绕通知
    @Around(value = "execution(* com.study.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint){
        System.out.println("around...之前");
        //被增强的方法执行
        try {
            proceedingJoinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("around...之后");
    }
    //最终通知
    @After(value = "execution(* com.study.User.add(..))")
    public void after(){
        System.out.println("after...");
    }
    //异常通知
    @AfterThrowing(value = "execution(* com.study.User.add(..))")
    public void afterThrowing(){
        System.out.println("afterThrowing...");
    }

}


 在通知方法运行时,可以拿到目标方法的详细信息;

需要为通知方法的参数列表上写一个参数JoinPoint joinPoint——>封装了当前目标方法的详细信息

    @Before(value = "execution(* com.study.User.add(..))")
    public void before(JoinPoint joinPoint){
        //获取方法签名
        Signature signature = joinPoint.getSignature();
        //获取参数
        Object[] args = joinPoint.getArgs();
        //方法名
        String name = signature.getName();
        System.out.println(name+":"+ Arrays.asList(args));
    }

 通过注解的参数,得到被增强方法反回值,异常等,但增强(通知)方法的参数不能随便写,因为通知方法时Spring利用反射调用的,每次方法调用得确定这个方法得参数表的值;参数表上的每一个参数,Spring都得知道是什么

//后置通知,通过参数returning拿到被增强方法的返回值
    @AfterReturning(value = "execution(* com.study.User.add(..))",returning = "result")
    public void afterReturning(Object result){
        System.out.println("优先afterReturning..."+result);
    }
    //异常通知,通过参数throwing拿到被增强方法的执行异常
    @AfterThrowing(value = "execution(* com.study.User.add(..))",throwing = "ex")
    public void afterThrowing(Exception ex){
        System.out.println("afterThrowing..."+ex);
    }

相同切入点抽取

    //相同切入点抽取
    @Pointcut(value = "execution(* com.study.User.add(..))")
    public void pointdemo(){}
    //前置通知
    @Before(value = "pointdemo()")
    public void befor(){
        System.out.println("befer...");
    }

增强类优先级 

有多个增强类对同一个方法进行增强,设置增强类优先级

在增强类上面添加注释@Order(数字类型值),数字类型值越小优先级越高

//增强类
@Component
@Aspect //生成代理对象
@Order(2)
class UserProxy{

基于xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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
        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/context/spring-aop.xsd">
    <!--创建对象-->
    <bean id="user" class="com.study.User"/>
    <bean id="userp" class="com.study.UserProxy"/>
    <!--配置aop增强-->
    <aop:config>
        <!--切入点-->
        <aop:pointcut id="p" expression="execution(* com.study.User.add(..))"/>
        <!--配置切面-->
        <aop:aspect ref="userp">
            <!--增强作用在具体的方法上-->
           <!--前置-->
            <aop:before method="befor" pointcut-ref="p"/>
           <!--后置-->
            <aop:after-returning method="afterReturning" pointcut-ref="p"/>
        </aop:aspect>
    </aop:config>
</beans>

 SpEl

是spring表达式的语言 #{}    <------------>区别${},引入外部配置文件值,如数据库配置

JdbcTemplate

Spring框架对Jdbc进行封装,使用JdbcTemplate方便实现对数据库操作

相关jar包

 数据库配置

 创建service类,创建dao类,在dao注入jdbcTemplate对象

class Book {
    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

interface BookDao {
    //添加方法
    void add(Book book);
}

@Repository
class BookDaoImpl implements BookDao {

    //注入JdbcTemplate对象
    @Autowired
    private JdbcTemplate jdbcTemplate;
    //添加方法
    @Override
    public void add(Book book) {
        String sql = "insert into t_book values(?,?)";
        int update = jdbcTemplate.update(sql, book.getId(), book.getName());
    }
}

@Service
class BookService {
    //注入dao
    @Autowired
    private BookDao bookDao;
    //添加的方法
    public void addBook(Book book) {
        bookDao.add(book);
    }
}

事务

事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果一个失败所有操作都失败

四个特性:原子性、一致性、隔离性、持久性

在spring进行事务管理操作有两种方式:编程式事务管理(try catch)和 声明式事务管理

声明式事务管理:基于注解方式、基于xml配置文件方式

在Spring进行声明式事务管理,底层使用AOP原理

事务管理API

提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类

 基于注解方式声明事务

 <!--    创建事务管理器-->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--        注入数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--    开启事务注解-->
    <tx:annotation-driven transaction-manager="transactionManager"/>

 完全注解

package com.study;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

@Configuration//作为配置类,替代xml配置文件
@ComponentScan(basePackages = {"com.study"})//开启扫描
@EnableAspectJAutoProxy//开启Aspect生成代理对象
@EnableTransactionManagement()//开启事务注解
public class Config {

    @Bean
    public DruidDataSource getDruidpool(){
        DruidDataSource druid = new DruidDataSource();
        druid.setUrl("");
        druid.setUsername("");
        druid.setPassword("");
        druid.setDriverClassName("com.mysql.jdbc.Driver");
        return druid;
    }

    @Bean
    public JdbcTemplate get(DataSource dataSource){
       //到ioc容器中根据类型找到druid
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        return jdbcTemplate;
    }
    @Bean
    public DataSourceTransactionManager getDA(DataSource dataSource){
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
        return transactionManager;
    }
}

@Transactional相关参数

 propagation:事务传播行为

ioslation:事务隔离级别

timeout:超时时间

readOnly:是否只读,默认false

rollbackFor:回滚,设置出现哪些异常进行事务回滚

noRollbackFor:不回滚,设置哪些异常不回滚

基于xml配置方式声明事务

配置事务管理器、配置通知、配置切入点

    <!--创建事务管理器-->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--配置通知-->
    <tx:advice id="txadvice">
        <!--配置事务参数-->
        <tx:attributes>
            <!--指定哪种规则的方法上面添加事务-->
            <tx:method name="add" propagation="REQUIRED"/>
            <!--<tx:method name="ad*"/>-->
        </tx:attributes>
    </tx:advice>

    <!--配置切入点和切面-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="pt" expression="execution(* com.study.User.*(..))"/>
        <!--配置切面-->
        <aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
    </aop:config>

spring5新特性

 webflux

webflux是一种异步非阻塞的框架,异步非阻塞的框架在Servlet3.1以后才支持,核心是基于Reactor的相关API实现的。

阻塞和非阻塞是针对被调用者,被调用者受到请求之后,做完请求任务之后才给反馈就是阻塞,收到请求之后立即给出反馈然后再去做事情就是非阻塞

异步和同步针对调用者,调用者发送请求,如果等着对方回应之后才去做其他事情就是同步,如果发送请求之后不等对方回应就去做其他的事情就是异步

待续!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值