Spring

Spring,第1张

Spring

文章目录
  • spring概念
    • 1.Spring 的发展历程
    • 2.spring 的优势
      • 1.方便解耦,简化开发
      • 2.AOP 编程的支持
      • 3.声明式事务的支持
      • 4.方便程序的测试
      • 5.方便集成各种优秀框架
      • 6.降低 JavaEE API 的使用难度
      • 7.Java 源码是经典学习范例
    • 3.spring 的体系结构
    • 4.spring在3层架构位置图解
  • IoC 的概念和作用
    • 1.什么是程序的耦合
      • 1.反射解耦
      • 2.工厂模式解耦
    • 2.控制反转-Inversion Of Control
  • 使用 spring 的 IOC 解决程序耦合
    • 1.准备 spring 的开发包
    • 2.导入spring核心包
    • 3.在类的根路径resource下创建一个任意名称的 xml 文件(不能是中文)
    • 4.测试配置是否成功
  • spring创建bean的三种方式
    • 1.第一种方式:使用默认构造函数创建。
    • 2.第二种方式:使用普通工厂中的方法创建对象。
    • 3.第三种方式:使用工厂中的静态方法创建对象。
    • 4.设置bean的作用范围
    • 5.我对普通工厂和静态工厂创建对象疑问
  • IOC中的依赖注入(DI)三种方式
    • 1.第一种:使用构造函数提供
    • 2.第二种:使用set方法提供
      • 1.set方式注入基本类型和string类型
      • 2.set方式注入复杂类型
    • 3.第三种:使用注解提供
  • spring注解介绍
    • 1.spring创建对象注解
    • 2.spring注入数据注解
      • 1.Autowired细节图解
      • 2.引入外部的属性文件(配置@Value使用)
      • 3.数据注解
    • 3.spring中设置bean作用范围注解
    • 4.spring设置生命周期方法注解
    • 5.spring中的新注解
  • Spring整合Junit测试

spring概念

Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control:反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层 Spring MVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的 Java EE 企业应用开源框架。

1.Spring 的发展历程

1997 年 IBM 提出了 EJB 的思想
1998 年,SUN 制定开发标准规范 EJB1.0
1999 年,EJB1.1 发布
2001 年,EJB2.0 发布
2003 年,EJB2.1 发布
2006 年,EJB3.0 发布
Rod Johnson(spring 之父)
Expert One-to-One J2EE Design and Development(2002)
阐述了 J2EE 使用 EJB 开发设计的优点及解决方案
Expert One-to-One J2EE Development without EJB(2004)
阐述了 J2EE 开发不使用 EJB 的解决方式(Spring 雏形)
2017 年 9 月份发布了 spring 的最新版本 spring 5.0 通用版(GA)

2.spring 的优势 1.方便解耦,简化开发

通过 Spring 提供的 IoC 容器,可以将对象间的依赖关系交由 Spring 进行控制,避免硬编码所造成的过度程序耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。

2.AOP 编程的支持

通过 Spring 的 AOP 功能,方便进行面向切面的编程,许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松应付。

3.声明式事务的支持

可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务的管理,提高开发效率和质量。

4.方便程序的测试

可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的 *** 作,而是随手可做的事情。

5.方便集成各种优秀框架

Spring 可以降低各种框架的使用难度,提供了对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的直接支持。

6.降低 JavaEE API 的使用难度

Spring 对 JavaEE API(如 JDBC、JavaMail、远程调用等)进行了薄薄的封装层,使这些 API 的使用难度大为降低。

7.Java 源码是经典学习范例

Spring 的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对 Java 设计模式灵活运用以及对 Java 技术的高深造诣。它的源代码无意是 Java 技术的最佳实践的范例。

3.spring 的体系结构

4.spring在3层架构位置图解

IoC 的概念和作用 1.什么是程序的耦合

在软件工程中,耦合指的就是就是对象之间的依赖性。对象之间的耦合越高,维护成本越高。因此对象的设计应使类和构件之间的耦合最小。软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。划分模块的一个准则就是高内聚低耦合。( 降低耦合性,可以提高其独立性)。

1.反射解耦
通过反射来注册驱动此时的好处是,我们的类中不再依赖具体的驱动类,此时就算删除 mysql 的驱动 jar 包,依然可以编译(运
行就不要想了,没有驱动不可能运行成功的)。
同时,也产生了一个新的问题,mysql 驱动的全限定类名字符串是在 java 类中写死的,一旦要改还是要修改源码。
解决这个问题也很简单,使用配置文件配置。

DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Class.forName("com.mysql.jdbc.Driver");//此处只是一个字符串
public class JdbcDemo1 {
    public static void main(String[] args) throws  Exception{
        //1.注册驱动
		//DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取连接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/eesy","root","1234");
        //3.获取 *** 作数据库的预处理对象
        PreparedStatement pstm = conn.prepareStatement("select * from account");
        //4.执行SQL,得到结果集
        ResultSet rs = pstm.executeQuery();
        //5.遍历结果集
        while(rs.next()){
            System.out.println(rs.getString("name"));
        }
        //6.释放资源
        rs.close();
        pstm.close();
        conn.close();
    }
}
2.工厂模式解耦

在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,让一个类中的方法通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。
那么,这个读取配置文件,创建和获取三层对象的类就是工厂。

public class BeanFactory {
    private static Properties p = null;
    private static HashMap hashMap = new HashMap<>();

    static {
        try {
            p = new Properties();
            InputStream is = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            p.load(is);
            //获取配置文件中所有键
            Enumeration keys = p.keys();
            //遍历所有键
            while (keys.hasMoreElements()) {
                //获取键
                String key = (String) keys.nextElement();
                //通过键获取类全名称
                String beanName = (String) p.get(key);
                //通过类全名称使用反射创建对象
                Object obj = Class.forName(beanName).newInstance();
                //将键和创建的对象存储到map集合中
                hashMap.put(key,obj);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    
    public static Object getBean(String beanName){
        return hashMap.get(beanName);
    }

    
    public static Object getBean2(String beanName) {
        Object obj = null;
        try {
            //通过键获取实体类名称
            String name = (String) p.get(beanName);
            obj = Class.forName(name).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return obj;
    }
}
 

web

public class AccountClient {
    //web层依赖service中的对象
    //private static AccountService as = new AccountServiceImpl();

    public static void main(String[] args) {
	    //使用工厂类创建对象,来解耦。
        AccountServiceImpl as = (AccountServiceImpl) BeanFactory.getBean("accountService");
        as.save();
    }
}

service

public class AccountServiceImpl implements AccountService {
    //service层依赖dao中的对象
    //private AccountDao ad= new AccountDaoImpl();

    @Override
    public void save() {
    	//使用工厂类创建对象,来解耦。
        AccountDaoImpl ad = (AccountDaoImpl) BeanFactory.getBean("accountDao");
        ad.save();
    }
}

dao

public class AccountDaoImpl implements AccountDao {
    @Override
    public void save() {
        System.out.println("存钱");
    }
}
2.控制反转-Inversion Of Control

上一小节解耦的思路有 2 个问题:

1、存哪去?
分析:由于我们是很多对象,肯定要找个集合来存。这时候有 Map 和 List 供选择。
	到底选 Map 还是 List 就看我们有没有查找需求。有查找需求,选 Map。
所以我们的答案就是
	在应用加载时,创建一个 Map,用于存放三层对象。
	我们把这个 map 称之为容器。

2、还是没解释什么是工厂?
	工厂就是负责给我们从容器中获取指定对象的类。这时候我们获取对象的方式发生了改变。
    原来:
    	我们在获取对象时,都是采用 new 的方式。是主动的。
	现在:
 		我们获取对象时,同时跟工厂要,有工厂为我们查找或者创建对象。是被动的。	

new方式图解

采用工厂图解

这种被动接收的方式获取对象的思想就是控制反转,它是 spring 框架的核心之一。

控制反转图解

明确 ioc 的作用:
	削减计算机程序的耦合(解除我们代码中的依赖关系)。
使用 spring 的 IOC 解决程序耦合 1.准备 spring 的开发包
官网:http://spring.io/
下载地址:
http://repo.springsource.org/libs-release-local/org/springframework/spring
解压:(Spring 目录结构:)
 docs:API 和开发规范.
 libs :jar 包和源码.
 schema :约束.


特别说明:
spring5 版本是用 jdk8 编写的,所以要求我们的 jdk 版本是 8 及以上。
同时 tomcat 的版本要求 8.5 及以上。

2.导入spring核心包

3.在类的根路径resource下创建一个任意名称的 xml 文件(不能是中文)

导入约束



  
	  
    
    
        
    

4.测试配置是否成功
获取spring的Ioc核心容器,并根据id获取对象
      ApplicationContext的三个常用实现类:
           ClassPathXmlApplicationContext:它可以加载类路径下的配置文件,要求配置文件必须在类路径下。不在的话,加载不了。(更常用)
           FileSystemXmlApplicationContext:它可以加载磁盘任意路径下的配置文件(必须有访问权限)
           AnnotationConfigApplicationContext:它是用于读取注解创建容器的。
     
      核心容器的两个接口引发出的问题:
      	   ApplicationContext:     单例对象适用              采用此接口
           它在构建核心容器时,创建对象采取的策略是采用立即加载的方式。也就是说,只要一读取完配置文件马上就创建配置文件中配置的对象。
     
           BeanFactory:            多例对象使用
           它在构建核心容器时,创建对象采取的策略是采用延迟加载的方式。也就是说,什么时候根据id获取对象了,什么时候才真正的创建对象。
      @param args

这个两个接口图解

web

public class AccountClient {
    public static void main(String[] args) {
        //创建spring容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //获取容器中对象
        AccountServiceImpl asi = (AccountServiceImpl) ac.getBean("accountService");
        AccountDaoImpl adi = (AccountDaoImpl) ac.getBean("accountDao");
        //调用方法
        asi.save();//保存service
        adi.save();//保存dao

        //--------BeanFactory----------
        //Resource resource = new ClassPathResource("bean.xml");
        //BeanFactory factory = new XmlBeanFactory(resource);
        //IAccountService as  = (IAccountService)factory.getBean("accountService");
        //System.out.println(as);
    }
}

service

public class AccountServiceImpl implements IAccountService{
    public void save() {
        System.out.println("保存service");
    }
}

dao

public class AccountDaoImpl implements IAccountDao {
    public void save() {
        System.out.println("保存dao");
    }
}
spring创建bean的三种方式
把对象的创建交给spring来管理
spring对bean的管理细节
   1.创建bean的三种方式
   		第一种方式:使用默认构造函数创建。
   		第二种方式: 使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器)
   		第三种方式:使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象,并存入spring容器)
   2.bean对象的作用范围
   3.bean对象的生命周期
1.第一种方式:使用默认构造函数创建。

第一种方式:使用默认构造函数创建。
在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时。
采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。

测试代码演示

public class AccountClient {
    public static void main(String[] args) {
        //创建spring容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //获取容器中对象
        AccountServiceImpl asi = (AccountServiceImpl) ac.getBean("accountService");
        //调用方法
        System.out.println(asi);//com.ginger.service.AccountServiceImpl@5b275dab
    }
}

spring配置文件



    
    
    

2.第二种方式:使用普通工厂中的方法创建对象。

第二种方式: 使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器)
spring为什么需要工厂和静态创建对象?
如果有一个类为了解耦不能使用构造直接创建对象(构造已有),而是用工厂来创建对象但是该类又在jar包里面所以修改不了源码所以所,以为了满足该需求spring就提供了工厂来创建对象。如果没有工厂创建对象呢?这个问题就是在扯淡了。如果一个类构造私有,还没有工厂方式创建该对象那这个类将毫无意义。

测试代码演示

public class AccountClient {
    public static void main(String[] args) {
        //创建spring容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //获取容器中对象
        AccountServiceImpl asi = (AccountServiceImpl) ac.getBean("accountService");
        //调用方法
        System.out.println(asi);//com.ginger.service.AccountServiceImpl@5b275dab
    }
}

工厂类

public class InstanceFacory {
    public AccountServiceImpl getBean(){
        return new AccountServiceImpl();
    }
}

spring配置文件



        
    
    
    

3.第三种方式:使用工厂中的静态方法创建对象。

第三种方式:使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象,并存入spring容器)
测试代码演示

public class AccountClient {
    public static void main(String[] args) {
        //创建spring容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //获取容器中对象
        AccountServiceImpl asi = (AccountServiceImpl) ac.getBean("accountService");
        //调用方法
        System.out.println(asi);//com.ginger.service.AccountServiceImpl@5b275dab
    }
}

静态工厂类

public class StaticFactory {
    public static AccountServiceImpl getBean(){
        return new AccountServiceImpl();
    }
}

spring配置文件




    
    

4.设置bean的作用范围

spring配置文件




    

    
    

5.我对普通工厂和静态工厂创建对象疑问

其实这个疑问时出现在配置文件中的,通过查看配置文件普通工厂和静态工厂配置方式不一致,难道就是因为一个方法不是静态,一个方法是静态的吗?其实就是这样的。

普通工厂
查看配置文件中普通工厂配置方式分析:
因为普通工厂中的方法是普通方法,所以要创建对象来调用所以在,所以在spring文件中配置工厂类,表示创建对象了,下面要调用方法了配置了一个调用方法并返回对象的配置。

静态工厂
查看配置文件中静态工厂配置方式分析:
静态工厂中的方法是静态的,所以我不需要创建对象来来调用方法,通过类名直接调用,就少了一个步骤。

我做过测试普通工厂按照静态工厂的配置方式就会报错。



   
    
    
    

    
    

IOC中的依赖注入(DI)三种方式
 spring中的依赖注入
        依赖注入:
            Dependency Injection
        IOC的作用:
            降低程序间的耦合(依赖关系)
        依赖关系的管理:
            以后都交给spring来维护
        在当前类需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中说明
        依赖关系的维护:
            就称之为依赖注入。
         依赖注入:
            能注入的数据:有三类
                基本类型和String
                其他bean类型(在配置文件中或者注解配置过的bean)
                复杂类型/集合类型
             注入的方式:有三种
                第一种:使用构造函数提供
                第二种:使用set方法提供
                第三种:使用注解提供
1.第一种:使用构造函数提供

测试代码演示

public class AccountClient {
    public static void main(String[] args) {
        //创建spring容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //获取容器中对象
        AccountServiceImpl asi = (AccountServiceImpl) ac.getBean("accountService");
        //调用方法
        //AccountServiceImpl{name='格雷福斯', age=35, date=Sat May 30 22:41:32 CST 2020}
        System.out.println(asi);
    }
}

AccountServiceImpl类

public class AccountServiceImpl implements IAccountService{
    private String name;
    private Integer age;
    private Date date;

    public AccountServiceImpl(String name, Integer age, Date date) {
        this.name = name;
        this.age = age;
        this.date = date;
    }

    public void save() {
        System.out.println("保存service");
    }

    @Override
    public String toString() {
        return "AccountServiceImpl{" +
                "name='" + name + ''' +
                ", age=" + age +
                ", date=" + date +
                '}';
    }
}

spring配置文件



   
    
    
        
        
        
    
    
    

2.第二种:使用set方法提供 1.set方式注入基本类型和string类型

测试代码演示

public class AccountClient {
    public static void main(String[] args) {
        //创建spring容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //获取容器中对象
        AccountServiceImpl2 asi = (AccountServiceImpl2) ac.getBean("accountService");
        //调用方法
        //AccountServiceImpl2{name='影流之主', age=26, date=Sat May 30 22:56:31 CST 2020}
        System.out.println(asi);
    }
}

AccountServiceImpl2类

public class AccountServiceImpl2 implements IAccountService{
    private String name;
    private Integer age;
    private Date date;

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

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

    public void setDate(Date date) {
        this.date = date;
    }

    public void save() {
        System.out.println("保存service");
    }

    @Override
    public String toString() {
        return "AccountServiceImpl2{" +
                "name='" + name + ''' +
                ", age=" + age +
                ", date=" + date +
                '}';
    }
}

spring配置文件



    
    
        
        
        
    
    
    

2.set方式注入复杂类型

测试代码演示

public class AccountClient {
    public static void main(String[] args) {
        //创建spring容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //获取容器中对象
        AccountServiceImpl3 asi = (AccountServiceImpl3) ac.getBean("accountService");
        //调用方法
        //AccountServiceImpl3{myStrs=[诺克, 盖伦, 鳄鱼], myList=[亚索, 劫, 泰隆], mySet=[薇恩, 女警, 奥巴马], myMap={辅助1=娜美, 辅助2=风女, 辅助3=璐璐}, myProps={打野3=剑圣, 打野2=男q, 打野1=盲僧}}。
        System.out.println(asi);
    }
}

AccountServiceImpl3类

public class AccountServiceImpl3 {
    private String[] myStrs;
    private List myList;
    private Set mySet;
    private Map myMap;
    private Properties myProps;

    public void setMyStrs(String[] myStrs) {
        this.myStrs = myStrs;
    }

    public void setMyList(List myList) {
        this.myList = myList;
    }

    public void setMySet(Set mySet) {
        this.mySet = mySet;
    }

    public void setMyMap(Map myMap) {
        this.myMap = myMap;
    }

    public void setMyProps(Properties myProps) {
        this.myProps = myProps;
    }

    @Override
    public String toString() {
        return "AccountServiceImpl3{" +
                "myStrs=" + Arrays.toString(myStrs) +
                ", myList=" + myList +
                ", mySet=" + mySet +
                ", myMap=" + myMap +
                ", myProps=" + myProps +
                '}';
    }
}

spring配置文件




     
    
        
        
            
                诺克
                盖伦
                鳄鱼
            
        
        
        
            
                亚索
                
                泰隆
            
        
        
        
            
                薇恩
                女警
                奥巴马
            
        
        
        
            
                
                
                    风女
                
                
                    璐璐
                
            
        
        
        
            
                盲僧
                男q
                剑圣
            
        
    

3.第三种:使用注解提供

在spring注解介绍里面有写这里就不写了。

spring注解介绍
曾经XML的配置:

    

1.spring创建对象注解
用于创建对象的
     他们的作用就和在XML配置文件中编写一个标签实现的功能是一样的
     Component:
         作用:用于把当前类对象存入spring容器中
         属性:
             value:用于指定bean的id。当我们不写时,它的默认值是当前类名,且首字母改小写。
     Controller:一般用在表现层
     Service:一般用在业务层
     Repository:一般用在持久层
     以上三个注解他们的作用和属性与Component是一模一样。
     他们三个是spring框架为我们提供明确的三层使用的注解,使我们的三层对象更加清晰

测试代码演示

//@Controller
public class AccountClient {
    public static void main(String[] args) {
        //创建spring容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //获取容器中对象
        IAccountService as = (AccountServiceImpl) ac.getBean("accountService");
        IAccountDao ad = (AccountDaoImpl) ac.getBean("accountDao");
        //调用方法
        as.save();//保存service
        ad.save();//保存dao
    }
}

service
这里我没有添加dao的依赖,其实就是测试创建对象的注解,没有测试注入数据的注解。

//@Component
@Service("accountService")
public class AccountServiceImpl implements IAccountService{
    public void save() {
        System.out.println("保存service");
    }
}

dao

//@Component
@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {
    public void save() {
        System.out.println("保存dao");
    }
}

spring配置文件
导入context新的约束




    
    

2.spring注入数据注解 1.Autowired细节图解

使用Autowired注入,如果Ioc容器中有多个类型匹配时怎么注入。

2.引入外部的属性文件(配置@Value使用)

定义属性文件
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///spring_day02
jdbc.username=root
jdbc.password=123



	

另一种方式:

3.数据注解
注入数据的注解作用就和在xml配置文件中的bean标签中写一个标签的作用是一样的
Autowired:
   作用:自动按照类型注入。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功。
         如果ioc容器中没有任何bean的类型和要注入的变量类型匹配,则报错。
         如果Ioc容器中有多个类型匹配时:
   出现位置:
       可以是变量上,也可以是方法上
   细节:
       在使用注解注入时,set方法就不是必须的了。
Qualifier:
   作用:在按照类中注入的基础之上再按照名称注入。它在给类成员注入时不能单独使用。但是在给方法参数注入时可以。
   属性:
       value:用于指定注入bean的id。
Resource
   作用:直接按照bean的id注入。它可以独立使用
   属性:
       name:用于指定bean的id。
以上三个注入都只能注入其他bean类型的数据,而基本类型和String类型无法使用上述注解实现。
另外,集合类型的注入只能通过XML来实现。

Value
   作用:用于注入基本类型和String类型的数据
   属性:
       value:用于指定数据的值。它可以使用spring中SpEL(也就是spring的el表达式)
               SpEL的写法:${表达式}

测试代码演示

//@Controller
public class AccountClient {
    public static void main(String[] args) {
        //创建spring容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //获取容器中对象
        IAccountService as = (AccountServiceImpl) ac.getBean("accountService");
        //AccountServiceImpl{accountDao=com.ginger.dao.AccountDaoImpl@69a10787, name='影流之主', age=28}
        System.out.println(as);
        //调用方法
        as.save();//存钱啦
    }
}

service

//@Component
@Service("accountService")
public class AccountServiceImpl implements IAccountService {
    //@Autowired//按照类型注入
    //@Qualifier("accountDao")//根据dao的id注入,但是不能单独使用需要@Autowired配合。
    @Resource(name = "accountDao")//根据bean的id注入
    IAccountDao accountDao;

    //使用@Value注解注入基本类型和String类型。
    @Value("影流之主")
    private String name;
    @Value("28")
    private Integer age;

    public void save() {
        accountDao.save();
    }

    @Override
    public String toString() {
        return "AccountServiceImpl{" +
                "accountDao=" + accountDao +
                ", name='" + name + ''' +
                ", age=" + age +
                '}';
    }
}

dao

@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {
    public void save() {
        System.out.println("存钱啦");
    }
}
3.spring中设置bean作用范围注解
他们的作用就和在bean标签中使用scope属性实现的功能是一样的
Scope
	作用:用于指定bean的作用范围
	属性:
	    value:指定范围的取值。常用取值:singleton prototype

测试代码

//@Controller
public class AccountClient {
    public static void main(String[] args) {
        //创建spring容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //获取容器中AccountServiceImpl1单例对象
        IAccountService as1 = (AccountServiceImpl1) ac.getBean("accountService1");
        IAccountService as2 = (AccountServiceImpl1) ac.getBean("accountService1");
        System.out.println(as1 ==as2);//true

        //获取容器中AccountServiceImpl2多例对象
        IAccountService as3 = (AccountServiceImpl2) ac.getBean("accountService2");
        IAccountService as4 = (AccountServiceImpl2) ac.getBean("accountService2");
        System.out.println(as3==as4);//false
    }
}

AccountServiceImpl1类

//@Component
@Service("accountService1")
@Scope("singleton")//设置bean作用范围为单例
public class AccountServiceImpl1 implements IAccountService {

    public void save() {
        System.out.println("保存service");
    }
}

AccountServiceImpl2类

//@Component
@Service("accountService2")
@Scope("prototype")//设置bean作用范围为多例
public class AccountServiceImpl2 implements IAccountService {

    public void save() {
        System.out.println("保存service");
    }
}
4.spring设置生命周期方法注解
他们的作用就和在bean标签中使用init-method和destroy-methode的作用是一样的
	PreDestroy
	   作用:用于指定销毁方法
	PostConstruct
	    作用:用于指定初始化方法

测试代码演示

//@Controller
public class AccountClient {
    public static void main(String[] args) {
        //创建spring容器对象
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //获取容器中对象
        IAccountService as1 = (AccountServiceImpl) ac.getBean("accountService");
        //调用方法
        as1.save();
        //main线程执行完后,spring还没来得及关闭,main就执行完了,所以就看不见AccountServiceImpl销毁方法,
        //手动销毁spring容器。
        ac.close();
        //初始化方法
        //保存service
        //销毁方法
    }
}

AccountServiceImpl类

//@Component
@Service("accountService")
public class AccountServiceImpl implements IAccountService {
    public void save() {
        System.out.println("保存service");
    }

    @PostConstruct
    public void init(){
        System.out.println("初始化方法");
    }

    @PreDestroy
    public void distory(){
        System.out.println("销毁方法");
    }
}
5.spring中的新注解
该类是一个配置类,它的作用和bean.xml是一样的
spring中的新注解
Configuration
   作用:指定当前类是一个配置类
   细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
ComponentScan
    作用:用于通过注解指定spring在创建容器时要扫描的包
    属性:
        value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
               我们使用此注解就等同于在xml中配置了:
                    
Bean
    作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
    属性:
        name:用于指定bean的id。当不写时,默认值是当前方法的名称
    细节:
        当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。
        查找的方式和Autowired注解的作用是一样的
import
    作用:用于导入其他的配置类
    属性:
        value:用于指定其他配置类的字节码。
                当我们使用import的注解之后,有import注解的类就父配置类,而导入的都是子配置类。
PropertySource
    作用:用于指定properties文件的位置
    属性:
        value:指定文件的名称和路径。
                关键字:classpath,表示类路径下

测试代码
AccountServiceTest类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class AccountServiceTest {
    @Autowired
    private IAccountService as = null;
    @Test
    public void testFindAll() {
        //3.执行方法
        List accounts = as.findAllAccount();
        for(Account account : accounts){
            System.out.println(account);
        }
    }
    @Test
    public void testFindOne() {
        //3.执行方法
        Account account = as.findAccountById(1);
        System.out.println(account);
    }
    @Test
    public void testSave() {
        Account account = new Account();
        account.setName("test anno");
        account.setMoney(12345f);
        //3.执行方法
        as.saveAccount(account);

    }
    @Test
    public void testUpdate() {
        //3.执行方法
        Account account = as.findAccountById(4);
        account.setMoney(23456f);
        as.updateAccount(account);
    }
    @Test
    public void testDelete() {
        //3.执行方法
        as.deleteAccount(4);
    }
}

QueryRunnerTest类

public class QueryRunnerTest {
    @Test
    public  void  testQueryRunner(){
        //1.获取容易
        ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
        //2.获取queryRunner对象
        QueryRunner runner = ac.getBean("runner",QueryRunner.class);
        QueryRunner runner1 = ac.getBean("runner",QueryRunner.class);
        System.out.println(runner == runner1);
    }
}

使用java类配置spring的bean.xml文件
SpringConfiguration类

//@Configuration
@ComponentScan("com.itheima")
@import(JdbcConfig.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {

}

JdbcConfig类

public class JdbcConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;
    
    @Bean(name="runner")
    @Scope("prototype")
    
    public QueryRunner createQueryRunner(@Qualifier("ds2") DataSource dataSource){
        return new QueryRunner(dataSource);
    }
    
    @Bean(name="ds2")
    public DataSource createDataSource(){
        try {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driver);
            ds.setJdbcUrl(url);
            ds.setUser(username);
            ds.setPassword(password);
            return ds;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
    @Bean(name="ds1")
    public DataSource createDataSource1(){
        try {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driver);
            ds.setJdbcUrl("jdbc:mysql://localhost:3306/eesy02");
            ds.setUser(username);
            ds.setPassword(password);
            return ds;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}

jdbcConfig.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///travel
jdbc.username=root
jdbc.password=1234

AccountServiceImpl类

@Service("accountService")
public class AccountServiceImpl implements IAccountService{
    @Autowired
    private IAccountDao accountDao;
    @Override
    public List findAllAccount() {
        return accountDao.findAllAccount();
    }
    @Override
    public Account findAccountById(Integer accountId) {
        return accountDao.findAccountById(accountId);
    }
    @Override
    public void saveAccount(Account account) {
        accountDao.saveAccount(account);
    }
    @Override
    public void updateAccount(Account account) {
        accountDao.updateAccount(account);
    }
    @Override
    public void deleteAccount(Integer acccountId) {
        accountDao.deleteAccount(acccountId);
    }
}

AccountDaoImpl类

@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {
    @Autowired
    private QueryRunner runner;
    @Override
    public List findAllAccount() {
        try{
            return runner.query("select * from account",new BeanListHandler(Account.class));
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    @Override
    public Account findAccountById(Integer accountId) {
        try{
            return runner.query("select * from account where id = ? ",new BeanHandler(Account.class),accountId);
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    @Override
    public void saveAccount(Account account) {
        try{
            runner.update("insert into account(name,money)values(?,?)",account.getName(),account.getMoney());
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    @Override
    public void updateAccount(Account account) {
        try{
            runner.update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void deleteAccount(Integer accountId) {
        try{
            runner.update("delete from account where id=?",accountId);
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

实体类

public class Account implements Serializable {
    private Integer id;
    private String name;
    private Float money;
    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 Float getMoney() {
        return money;
    }
    public void setMoney(Float money) {
        this.money = money;
    }
    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + ''' +
                ", money=" + money +
                '}';
    }
}
Spring整合Junit测试
使用Junit单元测试:测试的配置
Spring整合junit的配置
     1、导入spring整合junit的jar(坐标)。
     2、使用Junit提供的一个注解把原有的main方法替换了,替换成spring提供的。
            @Runwith
     3、告知spring的运行器,spring和ioc创建是基于xml还是注解的,并且说明位置。
         @ContextConfiguration
                 locations:指定xml文件的位置,加上classpath关键字,表示在类路径下。
                 classes:指定注解类所在地位置。
当使用spring 5.x版本的时候,要求junit的jar必须是4.12及以上。

spring整合junit包

使用spring整合junit测试代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:bean.xml")
public class AccountServiceTest {
    @Autowired
    private IAccountService as = null;
    
    
    @Test
    public void testFindAll() {
        //3.执行方法
        List accounts = as.findAllAccount();
        for (Account account : accounts) {
            System.out.println(account);
        }
    }
    @Test
    public void testFindOne() {
        //3.执行方法
        Account account = as.findAccountById(1);
        System.out.println(account);
    }
    @Test
    public void testSave() {
        Account account = new Account();
        account.setName("test anno");
        account.setMoney(12345f);
        //3.执行方法
        as.saveAccount(account);

    }
    @Test
    public void testUpdate() {
        //3.执行方法
        Account account = as.findAccountById(4);
        account.setMoney(23456f);
        as.updateAccount(account);
    }
    @Test
    public void testDelete() {
        //3.执行方法
        as.deleteAccount(4);
    }
}

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

原文地址: https://outofmemory.cn/zaji/5682254.html

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

发表评论

登录后才能评论

评论列表(0条)