栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring学习笔记

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring学习笔记

目录

Spring

什么是Spring

什么样的对象放入容器中

什么样的对象不放入容器中

使用Spring框架的步骤

Spring核心技术IOC

IOC:控制反转的思想

IOC的技术实现

IOC的作用

set注入

构造注入

自动注入

常用注解

使用注解的步骤

Spring核心技术AOP

AOP:面向切面编程

AOP的技术实现

AOP的作用

什么时候考虑使用AOP技术

AOP中的概念

AspectJ的使用步骤

通知注解:表示切面的执行时间

代理的使用方式

切入点表达式

Spring整合MyBatis

整合的想法

哪些对象交给Spring创建和管理


Spring

什么是Spring

什么是Spring

Spring是一个框架,Spring的核心技术是 IOC 和 AOP,这两种技术能够有效的实现解耦合

Spring是一个容器,容器中存放的是Java对象,我们程序员需要做的是把对象放入到容器中,让容器帮我们完成对象的创建以及对象属性的赋值。

什么样的对象放入容器中

什么对象需要放入容器中

  1. dao类

  2. service类

  3. controller类

  4. 工具类

怎么把对象放入到容器中

  1. 使用xml配置文件,在配置文件中使用标签来声明

  2. 可以使用注解

Spring容器中的单例

Spring容器中的对象默认都是单例的,例如:在容器中名称为"晚枫"的对象只有一个

什么样的对象不放入容器中

什么对象不放入Spring容器中

  1. servlet

  2. listener

  3. filter

  4. 实体类对象

    原因: 首先要明确service和entity的职责,对于service是功能的载体,类里有你自己写的大量方法,这些方法可复用。对于entity就只是数据的载体,类中最重要的就是各种属性了,这些属性只有在给它赋值的情况才具有价值,所以不可复用。而Spring为我们初始化实例(默认单例),new了一次后处处使用。回到问题,service中的方法无状态,可复用,所以一个程序员就一个对象就ok,但是对于实体类,他是有有状态的,你全局使用一个对象的时候,处处都在修改里面的值,这是不合理的。所以实体类没必要注入。

使用Spring框架的步骤

使用步骤

1、加入Spring框架的依赖


        org.springframework
        spring-context
        5.3.7

2、创建接口和实现类 Spring默认使用的是JDK动态代理(基于接口实现的),所以为了方便,我们创建接口和实现类。 话说回来,不创建接口也是可以的,那么我们就需要进行相应的配置让Spring使用CGLIB动态代理(基于继承实现的)

接口:

public interface SayHello {
    void sayHello(String name);
}

接口的实现类:

public class SayHelloImpl implements SayHello {
    @Override
    public void sayHello(String name) {
        System.out.println("Hello " + name);
    }
}

3、创建Spring的配置文件(文件一般命名为:applicationContext) 我们可以在配置文件中使用标签来声明我们需要放入容器的对象,这样就可以让容器帮我们创建对象和管理对象之间的关系(给对象的属性赋值),那么当我们需要使用到对象的时候,只需要从容器中获取我们需要的对象,而不用手动创建对象了。



    
    
    
    
    
    

4、使用容器中的对象 我们可以通过ApplicationContext接口和ClassPathXmlApplicationContext实现类中的getBean()方法来获取对象,并使用。

 
@Test
public void test(){
        String config = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        SayHello service = ac.getBean(SayHello.class);
        service.sayHello("晚枫");
}

结果:

Spring核心技术IOC

IOC:控制反转的思想

思想

指导开发人员在容器中,代码之外管理对象,给属性赋值,管理依赖

IOC的技术实现

IOC的技术实现是 DI (依赖注入)

开发人员在项目中只需要提供对象的名称,对象的创建、查找以及赋值都交给容器来完成

DI 技术的底层实现

Spring的核心技术IOC是使用DI来实现的,而DI的底层是反射机制。所以我们在创建实体类的时候,必须要有无参数的构造方法,因为反射机制创建对象默认调用无参数构造方法

IOC的作用

作用

IOC能够实现业务对象之间的解耦合 例如:service和dao对象之间的解耦合

接下来的例子中需要使用到的实体类

学校

@Data
@NoArgsConstructor
@AllArgsConstructor
public class School {
    private String name;
    private String address;
}

学生

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    private String name;
    private School school;
}

set注入

set注入的实现方式

Spring容器调用类的set方法实现属性赋值

简单类型


        
        

引用类型


        
        
        

构造注入

构造注入的实现方式

Spring调用类的有参数构造方法来完成对象的创建

简单类型


        
        

引用类型


        
        
        

自动注入

自动注入的实现方式

由Spring根据某些规则给类中的引用类型赋值,有byName和byType两种方式

byName方式

Java类中引用类型的属性名和bean中的id相同,就能够完成赋值


        
        




        
    

byType方式

Java类中引用类型的数据类型和bean中的class有同源关系,就能完成赋值

同源关系

同一个类 父子类关系 接口和实现类的关系


        
        



        
    	

常用注解

在使用注解时需要注意: 需要在Spring配置文件中声明组件扫描器,告诉Spring注解在什么地方

@Component

@Component

这个注解是用来创建对象的,在类上加入这个注解,就等于为这个类创建了一个对象

使用@Component的两种方式

@Component 不使用自定义名称:默认是类名首字母小写

@Component("自定义名称") 使用自定义名称:可以通过自定义名称获取对象

@Repository

@Repository

创建dao对象,用来访问数据库的,不常用

使用@Repository的两种方式

@Repository 不使用自定义名称:默认是类名首字母小写

@Repository("自定义名称") 使用自定义名称:可以通过自定义名称获取对象

@Service

@Service

创建Service对象,处理业务逻辑的,可以有事务功能

使用@Service的两种方式

@Service 不使用自定义名称:默认是类名首字母小写

@Service("自定义名称") 使用自定义名称:可以通过自定义名称获取对象

@Controller

@Controller

创建控制器对象的,接收请求,显示处理结果

使用@Controller的两种方式

@Controller 不使用自定义名称:默认是类名首字母小写

@Controller("自定义名称") 使用自定义名称:可以通过自定义名称获取对象

@Value

@Value

给简单类型的属性赋值

使用@Value的方式

在属性的上面加上@Value("值")即可

@Autowired

@Autowired

Spring框架中给引用类型的属性赋值的,支持byName,byType,默认是byType。原理是自动注入

使用@Autowired的byType方式

在引用类型的属性上面加上@Autowired即可

使用@Autowired的byName方式

在引用类型的属性上面加入另外一个注解即可 @Autowired @Qualifier("值"):告诉Spring要引用哪个对象

@Autowired的属性

required=true:表示引用类型赋值失败,程序报错,并终止执行。 required=false:表示引用类型如果赋值失败,程序正常执行,引用类型是null

@Resource

@Resource

jdk中的注解,给引用类型的属性赋值的,支持byName,byType,默认是byName。原理是自动注入

@Resource的机制

@Resource支持byName和byType方式,默认使用byName方式,但是当byName方式赋值失败的时候,会继续使用byType的方式进行赋值

使用@Resource的方式

在引用类型的属性上面加上@Resource即可

@Resource只使用byName的方式

在引用类型上面加入@Resource(name="值"):告诉Spring要引用哪个对象

使用注解的步骤

1、在类种加入注解

2、在Spring配置文件中,加入组件扫描器的标签

Spring核心技术AOP

AOP:面向切面编程

思想

AOP意思就是面向切面编程,可以用一句话概况AOP编程思想,即横向重复,纵向抽取。

AOP的技术实现

AOP的底层是动态代理

1、JDK动态代理,使用JDK发射包中的类实现创建代理对象的功能 要求:目标类必须实现接口

2、cglib代理,使用第三方的工具库,实现代理对象的创建 要求:目标类必须能够继承,不能是final修饰的 原理:继承,子类就是代理对象

AOP可以看作是动态代理的规范化,把动态代理的步骤进行了规范和定义

AOP的作用

作用

1、在目标类源代码不改变的情况下,给目标类增加功能

2、减少重复代码

3、专注业务功能的实现

4、解耦合:对业务方法和非业务方法进行解耦合

什么时候考虑使用AOP技术

1、当要在不修改源代码的情况下增加功能时,可以使用AOP

2、当要给项目多个类增加一个相同功能时,可以使用AOP

3、当要给业务方法增加事务,日志输出时,可以使用AOP

AOP中的概念

aspect:切面,就是给业务方法增加的功能,一般日志输出,事务,权限检查等都是切面

pointcut:切入点,是一个或多个JoinPoint的集合,表示执行切面功能的位置

advice:通知,也叫增强,表示切面执行的时间,例如:在目标方法之前,在目标方法之后等等

AspectJ的使用步骤

1、加入依赖


        org.springframework
        spring-aspects
        5.3.7

2、创建目标类和目标类的接口:处理业务功能 等会使用切面类来为目标类增加功能

接口:

public interface SayHello {
    void sayHello(String name);
}

实现类:

public class SayHelloImpl implements SayHello {
    @Override
    public void sayHello(String name) {
        System.out.println("Hello " + name);
    }
}

3、创建切面类:在类中定义要给目标类增加的功能的方法 在类的上面加入@Aspect 在类中定义方法,方法就是切面要执行的功能代码 还需要定义切入点表达式execution()

@Aspect
@Component
public class MyAspect {
    
    @Before("execution(* *..service..*.*(..))")
    public void startTime(JoinPoint joinPoint) {
        // 在目标方法执行之前,输入当前系统时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String currentTime = sdf.format(new Date());
        System.out.println("currentTime = " + currentTime);
    }
}

4、在Spring配置文件中声明AspectJ框架中的自动代理生成器标签 自动代理生成器:用来完成代理对象的自动创建功能的

 

如果有接口也想使用cglib代理方式,可以如下设置

 

5、从容器中获取目标对象,执行目标对象的方法,切面类中的方法也会执行

@Test
public void test02(){
        String config = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        SayHello proxy = ac.getBean(SayHello.class);
        proxy.sayHello("晚枫");

}

结果:

通知注解:表示切面的执行时间

@Before

@Before:前置通知,在目标方法之前执行切面的功能

@Aspect
public class MyAspect {

    
    // @Before:表示在目标类方法之前执行
    // 切入点表达式表示要为哪个类的哪个方法增加功能
    // @Before(value = "execution(public void com.hgc.ba01.SomeServiceImpl.doSome(String,Integer))")
    @Before(value = "execution(void *..ba01.*.*(..))")
    public void myBefore(){
        System.out.println("非业务方法执行,业务方法的执行时间为:" + new Date());
    }
}

@AfterReturning

@AfterReturning:后置通知,在目标方法之后执行,能够获取目标方法的返回值,当目标方法的返回值是一个对象时,能够修改对象中属性的值,如果目标方法的返回值不是一个对象,那么就不能修改目标方法的返回值

@Aspect
public class MyAspect {
    

    
    @AfterReturning(value = "execution(* *..ba02.SomeServiceImpl.add(..))", returning = "res")
    public void myAfterReturning(Object res){
        System.out.println("非业务方法,后置通知执行了");

        if (res != null) {
            res = 100;
        }
    }

    @AfterReturning(value = "execution(* *..SomeServiceImpl.update(..))", returning = "res")
    public void myAfterReturning2(Object res){
        System.out.println("非业务方法,后置通知执行了");
        if (res != null) {
            Student student = (Student) res;
            student.setName("张三");
            student.setAge(1);
        }
    }
}

@Around

@Around:环绕通知,能够在目标方法的前后增强功能,能够控制目标方法是否调用,能够修改目标方法的返回值,一般做事务的

@Aspect
public class MyAspect {
    
    @Around(value = "execution(* *..SomeServiceImpl.*(..))")
    public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
        Object result = null;
        System.out.println("环绕通知,在目标方法之前,输出时间:" + new Date());
        // 调用目标方法
        result = pjp.proceed();
        System.out.println("环绕通知,在目标方法之后,提交事务");
        // 修改目标方法的返回值
        result = "Hello aspectJ";
        return result;
    }
}

@AfterThrowing

@AfterThrowing:异常通知,在目标方法发生异常时执行

@Aspect
public class MyAspect {
    
    
    @AfterThrowing(value = "execution(* *..SomeServiceImpl.*(..))", throwing = "e")
    public void myAfterThrowing(Exception e){
        System.out.println("非业务方法执行, 发生的异常:" + e.getMessage());
    }
}

@After

@After:最终通知,总是会执行的,一般用来做资源清除的

// 声明这是一个切面类
@Aspect
public class MyAspect {
    
    
    @After(value = "execution(* *..SomeServiceImpl.*(..))")
    public void myAfter(){
        System.out.println("非业务方法,最终通知,总是会被执行");
    }
}

@Pointcut

@Pointcut:定义和管理切入点的辅助注解

@Aspect
public class MyAspect {

    

    
    @Pointcut(value = "execution(* *..SomeServiceImpl.doFourth(..))")
    private void myPt(){

    }

    @Before(value = "myPt()")
    public void myBefore(){
        System.out.println("非业务方法,前置通知,在目标方法之前执行");
    }

    @AfterReturning(value = "myPt()", returning = "res")
    public Object myAfterReturning(Object res){
        System.out.println("非业务方法,后置通知,在目标方法之后执行," +
                "当目标方法的返回值是一个对象时,能够修改目标方法的返回值。" +
                "如果目标方法的返回值不是一个对象,则不能修改");
        return res;
    }

    @Around(value = "myPt()")
    public Object myAround(ProceedingJoinPoint pjp) throws Throwable {

        Object res = null;
        res = pjp.proceed();
        System.out.println("环绕通知,能在目标方法前后增加功能,也能够控制目标方法是否调用,能修改目标方法的返回值");
        return res;
    }
}

代理的使用方式

如果目标类有接口,默认使用JDK的动态代理

 

如果目标类没有接口,默认使用cglib动态代理

目标类有接口的时候,也可以使用cglib代理

 

切入点表达式

execution([访问修饰符] 返回值 包名.类名.方法名称(方法的参数) [异常]) []表示可省略

Spring整合MyBatis

整合的想法

想法

使用Spring的IOC核心技术,把MyBatis框架中需要使用的对象交给Spring统一创建和管理

哪些对象交给Spring创建和管理

交给Spring创建和管理的对象

1、数据源DataSource,使用阿里的Druid连接池、

2、SqlSessionFactory对象,使用SqlSessionFactoryBean在内部创建 SqlSessionFactory

3、dao代理对象,使用MapperScanConfigure在这个类的内部调用 getMapper(),创建dao对象

4、Service对象

基本步骤:

1、加入依赖




    4.0.0

    com.wanfeng
    ch11-review-spring-mybatis
    1.0.0

    ch11-review-spring-mybatis
    
    http://www.example.com

    
        UTF-8
        1.8
        1.8
    

    
        
        
            junit
            junit
            4.11
            test
        
        
        
            mysql
            mysql-connector-java
            8.0.25
        
        
        
            org.mybatis
            mybatis
            3.5.7
        
        
        
            org.springframework
            spring-context
            5.3.7
        
        
        
            org.mybatis
            mybatis-spring
            2.0.6
        
        
        
            com.alibaba
            druid
            1.2.6
        
        
        
            org.springframework
            spring-tx
            5.3.7
        
        
        
            org.springframework
            spring-jdbc
            5.3.7
        
    

    
        
            
            
                src/main/java
                
                    ***.xml
                
            
            
                src/main/resources
                
                    **
public class Student {
    private Integer id;
    private String name;
    private Integer age;
    private String email;

    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;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Student() {
    }

    public Student(Integer id, String name, Integer age, String email) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.email = email;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + ''' +
                ", age=" + age +
                ", email='" + email + ''' +
                '}';
    }
}

3、创建dao接口

public interface StudentDao {
    Student queryStudentById(Integer id);
}

4、创建dao接口对应的mapper文件





    

5、创建service接口

public interface StudentService {
    Student getStudentById(Integer id);
}

6、创建service接口的实现类

// 注意:使用了注解,一定要加组件扫描器  
@Service
public class StudentServiceImpl implements StudentService {
    @Autowired
    private StudentDao studentDao;

    @Override
    public Student getStudentById(Integer id) {
        return studentDao.queryStudentById(id);

    }
}

7、创建MyBatis的主配置文件




    
    
        
        
    
    

8、创建Spring的配置文件(一般命名为applicationContext)



    
    

    
    
        
        
        
    

    
    
        
        
    

    
    
        
        
    

    
    

    
    
    
        
    
    
    
    
    


    

    
    
    
    
    
    
    
    
    
    
    
    
    
    


    
    
    
    
    
    
    
    
    

    


    

9、使用Spring容器中的对象

@Test
public void testGetStudentById(){
    String config = "applicationContext.xml";
    ApplicationContext ac = new ClassPathXmlApplicationContext(config);
    StudentService service = ac.getBean(StudentService.class);
    Student student = service.getStudentById(6);
    System.out.println("student = " + student);
}

结果:

=========================================================================作者:晚枫

链接:https://blog.csdn.net/q2570558854/article/details/121147392

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/434949.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号