2020-11-15 Spring

概述

轻量级
非入侵式
免费开源
控制反转(IOC)
面向切面编程(AOP)

解决企业应用开发的复杂性

Maven依赖

maven:
直接导入这一个依赖,会自动下载其他依赖


    org.springframework
    spring-webmvc
    5.2.0.RELEASE

控制反转IOC思想

dao包下创建接口和实现类
UserDao

package com.yimin.dao;

public interface UserDao {
    void getUser();//模拟获得全部用户
}

UserDaoImpl

package com.yimin.dao;

public class UserDaoImpl implements UserDao {
    @Override
    public void getUser() {
        System.out.println("mysql:得到所有用户信息...");
    }
}

UserDaoImpl2

package com.yimin.dao;

public class UserDaoImpl2 implements UserDao {
    @Override
    public void getUser() {
        System.out.println("oracle:得到所有用户信息...");
    }
}

service包下创建接口和实现类
UserService

package com.yimin.service;

public interface UserService {
    void getUser();
}

UserServiceImpl

package com.yimin.service;

import com.yimin.dao.UserDao;

public class UserServiceImpl implements UserService {
    private UserDao userDao;//这里不写死,使用set,将控制权转移给用户(Test)

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void getUser() {
        userDao.getUser();
    }
}

测试
MyTest

package com.yimin;

import com.yimin.dao.UserDaoImpl;
import com.yimin.dao.UserDaoImpl2;
import com.yimin.service.UserServiceImpl;
import org.junit.Test;

public class MyTest {
    @Test
    public void test(){
        UserServiceImpl userService = new UserServiceImpl();
        //通过set动态指定目标对象
        userService.setUserDao(new UserDaoImpl());
        userService.getUser();

        userService.setUserDao(new UserDaoImpl2());
        userService.getUser();
    }
}

在service中使用set方法,实现调用时可以动态指定dao对象
用户 --> 业务层(set)--> 数据访问层
主动权:程序员 --> 用户

步骤

  1. 创建maven项目
  2. 在pojo包下新建实体类User
package com.yimin.pojo;

public class User {
    private String name;

    public String getName() {
        return name;
    }

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

    public User(){}

    public User(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}
  1. resources目录下新建applicationContext.xml配置文件,通过bean创建User的对象



    
        
    

    
        
    


bean表示就是一个对象,id为对象名,class为类,property为对象属性赋值;
property为一般属性赋值时,使用value;
当属性是一个其他类的对象时,使用ref赋值,指向beans中已经配置好的对象id即可

  1. Test包下创建测试类,通过context获取容器中的对象
package com.yimin;

import com.yimin.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        User user1 = (User) context.getBean("user1");
        System.out.println(user1.getName());

        User user2 = (User) context.getBean("user2");
        System.out.println(user2.getName());
    }
}

这样一来,对象的创建工作就交给spring了,我们只需要从配置文件中取来用就行了;
这就是spring中的IOC思想:由主动编程改为被动接收

创建对象的方式:

spring默认采用无参构造函数创建对象

当然也可以用有参构造,使用有参构造时,使用标签constructor-arg
index是根据参数位置索引来赋值
type是根据参数类型来赋值,多个相同参数类型时,按照先后顺序对应
name是根据参数名来赋值(最形象)

 
    
        
    
    
    
        
    
    
    
        
    

其他标签

alias:别名


    

也可以直接在bean中使用name设置别名(可以设置多个,用逗号隔开)


        

import:导入spring配置文件,spring是可以有多个配置文件的,但最后只读一个


依赖注入DI

构造器注入

set注入(主要)

普通类型使用value
引用类型用ref(bean注入)
数组注入,在property中增加子标签:array,其他如list,set,map同
空值注入,value值为空即可
null注入,在property中增加子标签:
properties注入,在property中增加子标签:,再添加子标签
value

扩展方式

p命名空间注入(set注入)

引入p命名空间:

xmlns:p="http://www.springframework.org/schema/p"

之后直接使用p:属性赋值:


c命名空间注入(构造器注入)

引入c命名空间:(要有有参构造函数)

xmlns:c="http://www.springframework.org/schema/c"

使用方式和p命名相似,但是使用的是构造器注入,所以要有有参构造函数

bean属性scope:作用域

singleton:单例模式(默认)


        

prototype:原型模式

bean自动装配

显式地使用ref





        
        
        

autowire属性,自动寻找beans中创建的对象,为引用类型属性赋值

值:byName,对象的id要和属性的setXXX中的XXX对应,如将Dog的id设置为dog123,则不能完成自动注入





        

值:byType,匹配的是属性的类型,即class。此时id可以不要,class要唯一





        

通过注解实现自动装配,需要在xml中添加注解的支持



@Autowired可以在属性上使用,也可以在方法上使用

package com.yimin.pojo;

import org.springframework.beans.factory.annotation.Autowired;

public class People {

    private String name;
    @Autowired
    private Dog dog;
    @Autowired
    private Cat cat;
    ...
}

此时xml中就不用手动为Cat和Dog属性注入了,并且不需要Set方法了


    

    
    

    
        
    

@Autowired可以自动byType或byName寻找注入,首先会通过byType寻找,当有多个相同类型时,就会按byName寻找(setXXX中的XXX),否则找不到,这时可以使用@Qualifier(value="xxx"),xxx为id值,显式地指定注入对象

也可以使用@Resource注解,作用和 @Autowired相同,当按类型和按id都找不到时,可以通过@Resource(name="xxx"),xxx为id,显式地指定注入对象,同@Qualifier(value="xxx")


使用注解开发

新建一个spring项目,配置文件:




    
    


上面配置文件中指明了扫描pojo包下的@Component注解,用来代替bean,在pojo包下创建User实体类:

package com.yimin.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * 相当于bean,id为user(类名首字母小写)
 */
@Component
public class User {
    //相当于property属性注入,也可以放在setter方法上
    @Value("zhangsan")
    public String name;
}

使用@Value进行属性注入,相当于配置文件中的

测试以及运行结果

import com.yimin.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {

    @Test
    public void testUser(){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = ctx.getBean("user", User.class);
        System.out.println(user.name);
    }
}
zhangsan

pojo包对应的注解为@Component
controller包对应的注解为@Controller
service包对应的注解为@Service
dao包对应的注解为@Repository

其实作用都是作为bean装配到spring容器中,名称只是为了标识每个层

作用域使用@Scope("singleton")注解,标注在类上


使用配置类代替配置文件

pojo.User.java

package yimin.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * AppConfig中每个方法的返回值就是一个bean,这里就不用添加@Component了
 */
//@Component
public class User {
    @Value("zhangsan")
    private String name;

    public User() {
    }

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

创建config.AppConfig.java配置类

package yimin.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import yimin.pojo.User;

@Configuration
@ComponentScan("yimin.pojo")
public class AppConfig {
    @Bean
    public User getUser(){
        return new User();
    }
}

@Configuration 表明这是一个配置类,用来代替applicationContext.xml

@ComponentScan("yimin.pojo"):扫描指定包下的@Component注解,装配到spring容器中

@Bean:标注在方法上,将方法的返回值作为bean装配到spring容器中,id默认为方法名

以上提到了两种装配情况,使用@Bean时,其实没必要为返回值相同的类标注@Configuration,若同时又加上了@Configuration,配置类上又标注了@ComponentScan("yimin.pojo"),则spring容器中就存在两个User对象了,通过user(@Component装配的对象)和getUser(@Bean装配的对象)都可以获得User对象

测试

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import yimin.config.AppConfig;
import yimin.pojo.User;

public class MyTest {
    @Test
    public void testUser(){
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        User user = ctx.getBean("user", User.class);
        System.out.println(user.getName());
    }
}

这时由于没有使用xml配置文件,不能使用ClassPathXmlApplicationContext,而使用AnnotationConfigApplicationContext,参数为配置类

使用@Import()导入另一个配置类

你可能感兴趣的:(2020-11-15 Spring)