Spring 5

Spring 5,第1张

Spring 5 Spring 5

文章目录
  • Spring 5
    • Spring 框架概念
    • IOC容器
      • IOC概念和原理
        • 什么是ioc
        • ioc底层实现
        • IOC接口
        • IOC *** 作Bean管理
    • Spring的AOP
      • ***概念***
      • AOP***底层原理***
      • ***AOP术语***
      • ***AOP *** 作(准备工作)***
      • AOP *** 作(注解模式)
    • JDBCTemplate(了解)
      • 概念和准备工作
    • JDBCTemplate(了解)
      • 概念和准备工作

Spring 框架概念
  • spring是轻量级的开源的Java框架。

  • 可以解决企业应用开发的复杂性。

  • Spring 有两个核心;IOC和AOP

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

    AOP:面向切面(不修改的源代码的情况下,进行功能的

  • 特点:

    方便解耦,简化开发

    AOP编程的支持

    方便程序的测试

    方便和其他框架进行整合(后面的数据库 *** 作框架等)

    降低Java EE API的使用难度(对很多原生态的类进行封装)

    入门案例

    1.下载

    2.导入相关的jar包

    3.创建spring配置文件,在配置文件中配置创建对象的参数

    配置文件使用xml文件

    
    
    
        
    
    

    4.进行测试代码(简单的测试一下)

    package com.xixia.spring5_demo1;
    
    
    public class User {
        public void add(){
            System.out.println("通过spring自动创建对象,从而调用该方法");
        }
    }
    
    package com.xixia.spring5_demo1;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    
    public class User_Spring_test {
        @Test
        public void test_user_spring(){
            //1.加载配置文件
            ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean1.xml");
            //2.获取配置创建的对象
            User user=applicationContext.getBean("user",User.class);
            user.add();
        }
    }
    
IOC容器
  1. IOC底层原理
  2. IOC接口(BeanFactory)
  3. IOC *** 作Bean管理(基于XML)
  4. IOC *** 作Bean管理(基于注解)
IOC概念和原理 什么是ioc
  • 控制反转:把对象的创建,和对象之间的调用过程,交给spring进行管理
  • 使用ioc目的是:降低耦合度
  • 入门案例就是ioc实现
ioc底层实现
  • xml解析,工厂模式,反射

(工厂模式降低耦合度,耦合度不会消失的,只能尽量降低)

如果现在dao类路径改变,现在的耦合度只要求去修改xml文件中的值就可以了。对于那些应用的其让他类不需要任何修改

IOC接口
  • ioc思想基于IOC容器 完成,ioc容器底层就是对象工厂

  • spring提供ioc容器实现的两种方式(两个接口)

    (1)BeanFactory:ioc容器基本实现,是spring内部使用的接口,不提供开发人员进行使用

    加载配置文件时,不会创建对象,在获取(使用)对象时,才会去底层创建对象

    (2)ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般开发人员使用

    加载配置文件时,就会将配置文件中的对象进行创建

    ​ 一般而言,框架用在web开发中,会希望那些耗时较多的复杂 *** 作提前做好,不耽误数据的传输,和业务的处理。

    ApplicationContext接口有实现类:

IOC *** 作Bean管理

1.什么是Bean管理

  • spring创建对象
  • spring注入属性

2.Bean管理方式:

  • 基于XM配置文件方式
  • 基于注解方式

基于XML方式创建对象


  1. 使用bean标签,并且添加对应属性,就可以现实对象创建

  2. 在bean标签上有很多属性,常用属性有:

    id属性--------唯一标识

    class属性----类全路径

    name属性—和id一样。区别是可以加一些特殊符号

  3. 创建对象时,默认进行无参构造。

基于xml方式注入属性

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

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

    设置Bean类的set方法

    public class book {
        private String name;
        private int price;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getPrice() {
            return price;
        }
    
        public void setPrice(int price) {
            this.price = price;
        }
        public  book(){
    
        }
    }
    

    配置对应的xml文件

    
        
        
    
    

    spring框架的自动注入

    @Test
    public void test_book_xml(){
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean1.xml");
        book book=applicationContext.getBean("book", com.xixia.spring5_demo1.book.class);
        System.out.println(book.getName());
    
    }
    
  • 第二种:使用有参构造

    与第一种方法基本类似,设置Bean的有参构造,然后配置文件的属性,spring框架会自动注入。

    public book(String name,int price){
        this.name=name;
        this.price=price;
    }
    
    
        
        
    
    
    @Test
    public  void test_book_xml_arg(){
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean1.xml");
        book book=applicationContext.getBean("book", com.xixia.spring5_demo1.book.class);
        System.out.println(book.getPrice());
    }
    

IOc的外部注入

  • 创建两个类service类和dao类

    package com.xixia.dao;
    
    public interface Userdao {
        public void add();
    }
    
    //-----------------------------------------------
    package com.xixia.dao;
    
    
    public class UserdaoImpl  implements Userdao{
        @Override
        public void add() {
            System.out.println("userdaoImpl 实现接口userdao 中的add方法");
        }
    }
    //-----------------------------------------------
    package com.xixia.service;
    
    import com.xixia.dao.Userdao;
    import org.junit.Test;
    
    
    public class UserService {
        private Userdao userdao;
    
        public Userdao getUserdao() {
            return userdao;
        }
    
        public void setUserdao(Userdao userdao) {
            this.userdao = userdao;
        }
        public  void add(){
            userdao.add();
        }
    }
    
  • 在service类中调用dao中的方法

    public  void add(){
        userdao.add();
    }
    
  • 在spring配置文件中进行配置

    
        
        
    
    
    
    
  • 进行简单测试

    @Test
        public void test_UserService_waibuzhuru(){
            ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean1.xml");
            UserService userService=applicationContext.getBean("userService", com.xixia.service.UserService.class);
            userService.add();
        }
    

IOC的内部bean和级联赋值

例子:一对多关系:部门和员工

在实体类之间表示一对多关系

内部bean:


    
    
    

级联赋值

IOC注入集合属性

  1. 注入数组类型

  2. 注入List集合属性

  3. 注入Map集合属性

    package com.xixia.day02;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    
    public class collection_ioc {
        private String[] course;
        private List list;
        private Mapmap;
    
        public Set getSet() {
            return set;
        }
    
        public void setSet(Set set) {
            this.set = set;
        }
    
        private Setset;
    
        public String[] getCourse() {
            return course;
        }
    
        public void setCourse(String[] course) {
            this.course = course;
        }
    
        public List getList() {
            return list;
        }
    
        public void setList(List list) {
            this.list = list;
        }
    
        public Map getMap() {
            return map;
        }
    
        public void setMap(Map map) {
            this.map = map;
        }
    
        public void print(){
            System.out.println(Arrays.toString(course));
        }
    }
    
     
        
            
                java
                java2
            
        
    
        
        
            
                list1
                list2
            
        
    
    
        
        
            
                
                
            
        
    
        
        
            
               set1
                set2
            
        
    
    
    
    
    @Test
    public void test_collection(){
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean2.xml");
        collection_ioc collection_ioc=applicationContext.getBean("collection_ioc", com.xixia.day02.collection_ioc.class);
        collection_ioc.print();
    

    补充细节:在集合中设置对象元素+把集合注入部分提取出来,共享集合。

    
        
            
            
            
        
    
    .....
    
    
    
    

    集合提取出来

    util的命名空间()

    
    
    

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

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

    第三步配置spring配置文件

    package com.xixia.day02;
    
    import com.xixia.day01.spring5_demo1.book;
    import org.springframework.beans.factory.FactoryBean;
    
    
    public class FactoryBean_demo implements FactoryBean{
        @Override
        public book getObject() throws Exception {
            book book=new book("西游记",50);
            return book;
        }
    
        @Override
        public Class getObjectType() {
            return null;
        }
    
        @Override
        public boolean isSingleton() {
            return false;
        }
    }
    
    
    
    

    测试

    @Test
    public void test_factoryBean(){
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean2.xml");
        book book=applicationContext.getBean("factoryBean", com.xixia.day01.spring5_demo1.book.class);
        System.out.println(book.toString());
    }
    

    总结一下:就是通过设置工厂bean,来获得目的对象的实例,然后通过方法返回。在配置文件中配置对应设置,可以在测试中得到返回对象


Bean***的作用域***

在spring里面,设置bean实例是单实例还是多实例。

默认是单实例对象

设置多实例,bean标签里面有个属性:scope----->默认值singtelon.多实例:prototype

singtelon和prototype区别

1.singtelon,加载spring配置文件时就会创建对象

2.prototyp,get对象时才会创建对象


Bean的生命周期

  • 通过构造方法创建bean实例

  • 为bean的属性注入

  • 调用bean的初始化方法(需要进行配置初始化方法)bean标签有个属性init-method.将需要进行初始化的方法名传入即可

  • bean使用阶段

  • 当容器关闭,bean销毁(需要自己配置)同理初始化方法。destory-method.

    先关容器(application.close()),容器会根据配置文件来自动执行销毁方法。


Bean后置处理器,生命周期合计7步(不理解)

  • 通过构造方法创建bean实例

  • 为bean的属性注入

  • 把bean的实例传给bean的后置处理器的方法

  • 调用bean的初始化方法(需要进行配置初始化方法)bean标签有个属性init-method.将需要进行初始化的方法名传入即可

  • 把bean的实例传给bean的后置处理器的方法

  • bean使用阶段

  • 当容器关闭,bean销毁(需要自己配置)同理初始化方法。destory-method.

    先关容器(application.close()),容器会根据配置文件来自动执行销毁方法。

在当前spring文件中配置一个后置处理类,那么该配置文件的其他bean在创建的时候都会去调用一下后置处理器的方法(感觉类似拦截器)


XML***自动装配***

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





引入外部属性文件

当xml文件中固定配置的参数过多时,可以将这些数据提取出来放在外部,在xml文件中引用一下即可,一般应用到数据库的时候会用到这个方法。



    
    
        
        
        
        
    


    
    
    
        
        
        
        
    

基于注解方式的管理

一些简单概念

注解是代码特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性。。。。)

​ 使用注解的范围,可以在类,属性,方法上面

​ 使用注解的目的:简化xml的配置

Spring针对Bean管理中创建对象提供注解

​ @Component

​ @Service

​ @Controller

​ @Repository

上面四个注解功能是一样的,都可以用来创建bean实例。只是在不同的逻辑层中使用不同的注解,语义更清晰


使用注解的流程

  • 引入外部依赖jar包

  • 编写spring文件

        
    
  • 编写对应的bean,并给bean赋予注解

    package com.xixia.day03.Service;
    
    import org.springframework.stereotype.Service;
    
    
    @Service
    //注解后面的属性value相当与xml配置bean中的id.默认是该类的类名(首字母小写)
    public class UserService {
        public void add(){
            System.out.println("通过注解来实现,让spring创建bean对象");
        }
    }
    

    备注:组件扫描的细节:

    
    	
        
    

基于注解的属性注入

@Autowired:根据属性类型进行注入
@Qualifier:根据属性名称进行注入。记住需要和@Autowired一起搭配使用。
@Resource:不是Spring框架提供的,属于Java扩展包提供的功能。既可以是名称注入也可以是属性类型注入
@Value():普通属性直接注入。

补充细节:

第一点:@Autowired根据属性类型进行注入,现实情况是某个接口会有多个实现类,此时如果单单根据属性类型进行注入,spring框架无法判断出是要注入那个实现类。因此搭配根据属性名称一起。就是为了防止此类情况。

第二点:前三个都是bean的注入,后一个才是普通属性注入,而且一般都是将属性值存放在properties文件中,通过配置spring中的配置,去获取属性值${keyname}

@Service
//注解后面的属性value相当与xml配置bean中的id.默认是该类的类名(首字母小写)
public class UserService {
    @Autowired
    @Qualifier("userDaoImpl")
    private UserDao userDao;
    public void add(){
        System.out.println("通过注解来实现,让spring创建bean对象");
        userDao.user_dao_add();
    }
@Repository
public class UserDaoImpl implements UserDao {
    @Override
    public void user_dao_add() {
        System.out.println("注解方式,进行属性注入");
    }
@Component
public interface UserDao {
    public void user_dao_add();
}

Spring的AOP 概念

什么是AOP::面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各个部分之间耦合度降低,同时提高开发效率。

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


AOP***底层原理***

(。AOP底层使用了动态代理。。不太理解动态代理细节,也不明白代理在AOP中的作用)

有两种动态代理情况:

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

创建接口实现类的代理对象,实现增强功能

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

创建子类的代理对象,实现增强功能

JDK动态代理代码(演示,理解一下底层。spring5早已经将这些动态代理封装好了,认识和调用就行

package com.xixia.day03.dao;

public interface dynamic_Proxy_JDK_dao {
    public int add(int a,int b);
    public  void count();
}
package com.xixia.day03.dao;


public class dyamic_Proxy_JDK_dao_Impl implements dynamic_Proxy_JDK_dao {

    @Override
    public int add(int a, int b) {
        System.out.println("原始实现类的add方法");
        return (a+b);
    }

    @Override
    public void count() {
        System.out.println("原始实现类的count方法");

    }
}
package com.xixia.day03;


import com.xixia.day03.dao.dyamic_Proxy_JDK_dao_Impl;
import com.xixia.day03.dao.dynamic_Proxy_JDK_dao;

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


public class dynamic_Proxy_JDK {

    public static void main(String[] args) {
        Class[] interfaces={dynamic_Proxy_JDK_dao.class};
//        Proxy.newProxyInstance(dynamic_Proxy_JDK.class.getClassLoader(), interfaces, new InvocationHandler() {
//            @Override
//            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                return null;
//            }
//        });

        dynamic_Proxy_JDK_dao template=new dyamic_Proxy_JDK_dao_Impl();
        dynamic_Proxy_JDK_dao improve=(dynamic_Proxy_JDK_dao)Proxy.newProxyInstance(dynamic_Proxy_JDK.class.getClassLoader(), interfaces, new dynamic_Proxy_JDK_improve(template));
        int result=(Integer)improve.add(3,6);
        System.out.println(result);
    }
}

class dynamic_Proxy_JDK_improve implements InvocationHandler{
    private  Object obj;
    public dynamic_Proxy_JDK_improve(Object obj){
        this.obj=obj;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("原始方法执行前,可以添加的逻辑");
        Object res=method.invoke(obj,args);//执行原始方法
        System.out.println("原始方法执行完成后,可以添加的逻辑");

        return res;
    }
}

备注:对于这个理解,就是在原始的接口实现类上,不改变原始代码基础之上添加一些额外的代码功能。具体实现:通过JDK代理,增强部分需要实现接口InvocationHandler。然后通过Proxy.newProxyInstance()函数返回一个接口实现类的代理对象。


AOP术语


AOP *** 作(准备工作)
  • Spring框架一般都是基于AspectJ实现AOP *** 作的

  • AspectJ不是Spring组成部分,独立的AOP框架,一般把Aspect J和Spring框架一起使用,进行AOP *** 作。

  • 基于Aspect J实现AOP *** 作

    ​ 基于XML配置文件实现

    ​ 基于注解方式实现(常用)


切入点表达式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-erQw5PK2-1636198949962)(C:UsersxixiaAppDataRoamingTyporatypora-user-imagesimage-20211030151710532.png)]


AOP *** 作(注解模式)
  1. 创建类,在类里面定义方法

    package com.xixia.day03.AOP_annotation;
    
    import org.springframework.stereotype.Component;
    
    
    @Component
    public class base_class {
        public  int add(int a,int b){
            System.out.println("原始类执行结果");
            return (a+b);
        }
    }
    
  2. 创建增强类(编写增强逻辑)

    ​ 在增强类中编写不同方法,代表不同的通知类型

  3. 进行通知的配置

    ​ 在Spring中配置注解扫描

    ​ 使用注解创建原始类和增强类

    ​ 在增强类上添加注解@Aspect

    ​ 在Spring配置文件中开启生成代理对象

    package com.xixia.day03.AOP_annotation;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Component;
    
    
    @Component
    @Aspect
    public class improve_class {
    
        @Before(value = "execution(* com.xixia.day03.AOP_annotation.base_class.add(..))")
        public void before(){
            System.out.println("原始类add方法执行前,增加的逻辑");
        }
    //    @After()
    //    @AfterReturning()
    //    @Around()
    //    @AfterThrowing()
        //备注:@After()原始方法结束后就会执行通知。@AfterReturning()原始方法返回后会执行通知。区别在于如果方法出现异常或者中断,前者会执行而后者不会执行
        //@Around()有些特殊,看实例
    
        @Around(value = "execution(* com.xixia.day03.AOP_annotation.base_class.add(..))")
        public int Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            System.out.println("原始类add方法执行前,Around增加的逻辑");
            proceedingJoinPoint.proceed();//原始方法执行
            System.out.println("原始类add方法执行后,Around增加的逻辑");
            return 0;
    
    
        }
    }
    
  4. 配置不同类型通知

    
    
    
    
    
    

补充细节:
相同切入点抽取

@Pointcut(value="相同的切入点表达式")
public void pointcut(){

}

//用的时候直接填写方法,
@Before(value="pointcut()")

有多个增强类对同一个原始类的方法进行增强,可以设置优先级。

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


JDBCTemplate(了解)

备注:了解一下,spring如何整合了jdbc模板,为后期的mybati等其他模块的整合增加理解。

概念和准备工作
//@Around()有些特殊,看实例

   @Around(value = "execution(* com.xixia.day03.AOP_annotation.base_class.add(..))")
   public int Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
       System.out.println("原始类add方法执行前,Around增加的逻辑");
       proceedingJoinPoint.proceed();//原始方法执行
       System.out.println("原始类add方法执行后,Around增加的逻辑");
       return 0;


   }

}

4. 配置不同类型通知

```xml






补充细节:
相同切入点抽取

@Pointcut(value="相同的切入点表达式")
public void pointcut(){

}

//用的时候直接填写方法,
@Before(value="pointcut()")

有多个增强类对同一个原始类的方法进行增强,可以设置优先级。

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


JDBCTemplate(了解)

备注:了解一下,spring如何整合了jdbc模板,为后期的mybati等其他模块的整合增加理解。

概念和准备工作

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5120397.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-17
下一篇 2022-11-17

发表评论

登录后才能评论

评论列表(0条)

保存