spring学习笔记(上)


1、Spring

简介

spring整合了现有的技术框架。

官方文档

导入依赖包

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.15</version>
</dependency>

优点(特点)

  • 开源的免费框架(容器)
  • 轻量级、非入侵式(不改变原有代码)的框架
  • 控制反转(IOC),面向切面编程(AOP)
  • 支持事务的处理,对框架整合的支持

2、IOC(控制反转)理论的理解

传统开发流程:

  1. UserDao接口
public interface UserDao {
    void getUser();
}
  1. UserDaoImpl
public class UserDaoImpl implements UserDao{
    public void getUser() {
        System.out.println("获取UserDao对象");
    }
}
  1. UserService
public interface UserService {
    void getUser();
}
  1. UserServiceImpl
public class UserServiceImpl implements UserService{

    private UserDao userDao = new UserDaoImpl();

    public void getUser() {
        userDao.getUser();
    }
}
  1. 测试
public class MyTest {

    public static void main(String[] args) {

        //用户实际调用的是业务层,dao层他们不需要接触
        UserServiceImpl userService = new UserServiceImpl();
        userService.getUser();
    }
}


当用户改变了需求时,(使用UserDaoMysqlImpl 需求)

public class UserDaoMysqlImpl implements UserDao{
    public void getUser() {
        System.out.println("MySql获取User");
    }
}

需要程序员根据用户需求去改变业务层代码(如果程序庞大,这需要程序员花费昂贵的代价修改原来的代码)

public class UserServiceImpl implements UserService{
								//改变了实现的接口
    private UserDao userDao = new UserDaoMysqlImpl();

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

使用set实现动态的改变接口

public class UserServiceImpl implements UserService{

    private UserDao userDao;
    //使用set,使得可以动态的改变接口
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

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

使得用户可以自己选择需求

public class MyTest {

    public static void main(String[] args) {

        //用户实际调用的是业务层,dao层他们不需要接触
        
        UserServiceImpl userService = new UserServiceImpl();
        //用户选择实现哪个接口
        userService.setUserDao(new UserDaoMysqlImpl());

        userService.getUser();
    }
}

  • 之前是程序员主动创建对象,控制权在程序员手上
  • 使用set之后,程序不再具有主动性,而是变成了被动的接受对象

这种思想,从本质上解决了问题,程序员不用再去管理对象的创建了。系统的耦合性大大降低,可以更加专注在业务的实现上。这就是IOC(控制反转)的原型!

IOC(Inversion of Control)本质:控制反转是一种设计思想,在没有IOC的程序中,对象的创建与对象之间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方。

控制反转通过描述(XML或注解)经由第三方去生产或获取特定对象。在spring中实现控制反转的是IOC容器,其实现方式是依赖注入(Dependency Injection,DI)。

在这里插入图片描述

3、hello spring

导入依赖包

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.15</version>
</dependency>

创建实体类

public class Hello {
    private String str;

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

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }

}

Spring IoC 容器 使用XML的方式配置元数据

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="hello" class="pojo.Hello">
        <property name="str" value="spring"/>
    </bean>

</beans>

实例化容器,并使用容器

public class MyTest {
    public static void main(String[] args) {
    	//实例化容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //使用容器
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello.getStr());
    }
}

以上程序中:

  • hello对象是由spring容器创建,
  • hello对象的属性值是spring容器设置的

这个过程就是控制反转

控制:使用spring后,对象是由springIOC容器创建
反转:程序本身不创建对象,而变成被动的接收对象

依赖注入:就是使用set方法来进行注入

现在,我们彻底不用再去修改程序,要实现不同的操作,只需在xml配置文件中进行修改



使用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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="defaultImpl" class="dao.UserDaoImpl"/>
    <bean id="MysqlImpl" class="dao.UserDaoMysqlImpl"/>
    <!--根据需要修改ref-->
    <bean id="service" class="service.UserServiceImpl">
        <property name="userDao" ref="defaultImpl"/>
    </bean>
</beans>
public class MyTest {

    public static void main(String[] args) {
/*
        //用户实际调用的是业务层,dao层他们不需要接触
        UserServiceImpl userService = new UserServiceImpl();
        //用户选择实现哪个接口
        userService.setUserDao(new UserDaoMysqlImpl());
        userService.getUser();
*/
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        UserServiceImpl service = (UserServiceImpl) context.getBean("service");
        service.getUser();
    }
}

4、IOC创建对象的方式

  • IOC容器创建对象时,自动调用了对象的无参构造函数
  • 创建对象时,创建了该配置文件中的所有对象,无论有没有被使用
  • 在配置文件加载的时候,容器中的对象就已经初始化了
	ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
	User user = (User) context.getBean("user");
  1. 下标赋值
    <bean id="user" class="pojo.User">
        <constructor-arg index="0"  value="张3"/>
    </bean>
  1. 类型赋值(不建议使用)
    <bean id="user" class="pojo.User">
        <constructor-arg type="java.lang.String"  value="张3"/>
    </bean>
  1. 参数名赋值
    <bean id="user" class="pojo.User">
        <constructor-arg name="name"  value="张3"/>
    </bean>

5、spring配置

5.1 别名

  1. 使用alias标签
    <alias name="user" alias="u1"/>
    <bean id="user" class="pojo.User">
        <constructor-arg name="name"  value="张3"/>
    </bean>
public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        							  //使用别名
        User user = (User) context.getBean("u1");
        System.out.println(user.getName());
    }
}
  1. 在bean中使用name属性(推荐使用)
  	<!--空格 分号 逗号都可以当作分割-->
    <bean id="user" class="pojo.User" name="u2 u3;u4,u5">
        <constructor-arg name="name"  value="张3"/>
    </bean>

5.2 在配置文件中使用其他配置文件

applicationContext.xml

    <import resource="beans.xml"/>

6、依赖注入

依赖注入:本质上就是set注入

  • 依赖:bean对象的创建依赖于容器
  • 注入:bean对象中的所有属性,由容器来注入

构造器注入

    <bean id="user" class="pojo.User">
        <constructor-arg name="name"  value="张3"/>
    </bean>

set方式注入(重点)

public class Student {
    private String name;
    private Address address;
    private String[] books;
    private List<String> hobbies;
    private Map<String,String> card;
    private Set<String> games;
    private Properties info;
     ......
    }
   
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

<bean class="pojo.Address" id="address">
        <property name="address" value="xian"/>
</bean>

<bean id="student" class="pojo.Student">
    <!--普通属性,value-->
    <property name="name" value="张三"/>

    <!--bean注入,ref-->
    <property name="address" ref="address"/>

    <!--数组-->
    <property name="books">
        <array>
            <value>西游记</value>
            <value>红楼梦</value>
            <value>水浒传</value>
            <value>金瓶梅</value>
        </array>
    </property>

    <!--list-->
    <property name="hobbies">
        <list>
            <value>上网吧</value>
            <value>找妹子</value>
            <value>打游戏</value>
        </list>
    </property>

    <!--map-->
    <property name="card">
        <map>
            <entry key="id" value="1814040123"/>
            <entry key="name" value="小明"/>
        </map>
    </property>

    <!--set-->
    <property name="games">
        <set>
            <value>lol</value>
            <value>索尼子</value>
        </set>
    </property>

    <!--properties-->
    <property name="info">
        <props>
            <prop key="driver">com.mysql.jdbc.Driver</prop>
            <prop key="username">root</prop>
            <prop key="password">123</prop>
        </props>
    </property>
    
</bean>

</beans>

扩展方式注入

  1. p命名空间(property)
    使用时需要导入xml约束 xmlns:p="http://www.springframework.org/schema/p"
<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="pojo.User" p:username="张三" p:age="18" p:sex="1"/>

</beans>
  1. c命名空间(constructs-arg)
    需要相对应的构造函数才能使用
    使用时需要导入xml约束 xmlns:c="http://www.springframework.org/schema/c"
<?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:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user2" class="pojo.User" c:username="李四" c:age="20" c:sex="0"/>
</beans>

7、Bean作用域

单例模式(默认)

在IOC容器中创建一个对象,所有地方共用这一个对象
在这里插入图片描述

                                     				                 <!--不写默认为singleton-->
    <bean id="user" class="pojo.User" p:username="张三" p:age="18" p:sex="1" scope="singleton"/>
    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("userBeans.xml");
        User user = context.getBean("user", User.class);
        User user2 = context.getBean("user", User.class);
        System.out.println(user==user2);     //true
    }

原型模式

每次从容器中get时都会产生一个新对象
在这里插入图片描述

    <bean id="user" class="pojo.User" p:username="张三" p:age="18" p:sex="1" scope="prototype"/>
    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("userBeans.xml");
        User user = context.getBean("user", User.class);
        User user2 = context.getBean("user", User.class);
        System.out.println(user==user2);     //false
    }

其他的(request、session、application、websocket只在web开发中用到)

8、自动装配Bean

之前的bean注入,需要自己注入属性值

    <bean id="dog" class="Dog"/>
    <bean id="cat" class="Cat"/>

    <bean id="people" class="People" >
        <property name="dog" ref="dog"/>
        <property name="cat" ref="cat"/>
    </bean>

byName

  • 使用byName,需要保证所有bean的id唯一,并且id要和自动注入的属性的set方法的值一致
    <!--如果id改为dog1则报错-->
    <bean id="dog" class="pojo.Dog"/>
    <bean id="cat" class="pojo.Cat"/>

    <bean id="people" class="People" autowire="byName"/>

byType

  • 使用byType,需要保证所有bean的class唯一,并且class要和自动注入的属性的类型一致
    <!--如果id改为dog1也能正确运行-->
    <bean id="dog" class="pojo.Dog"/>
    <bean id="cat" class="pojo.Cat"/>

    <bean id="people" class="People" autowire="byType"/>

使用注解实现自动装配

  • 使用注解的方式要优于使用xml配置文件

使用注解:

  1. 导入xml约束context
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

</beans>
  1. 配置注解的支持 <context:annotation-config/>

@Autowired 注解:

  • 默认通过byType的方式实现,如果有多个类型相同,则通过byName方式实现
  • 直接在属性上使用@Autowired,也可以在set方法上使用
  • @Autowired(required = false) 表示这个对象可以为null,默认为true不允许为空
    <context:annotation-config/>

    <bean id="people" class="People"/>
    <bean id="cat" class="Cat"/>
    <bean id="dog" class="Dog"/>
public class People {
    @Autowired(required = false)
    private Cat cat;
    @Autowired
    private Dog dog;
......
}

如果@Autowired自动装配的环境比较复杂,无法通过一个注解完成的时候,可以使用 @Qualifier去配置@Autowired,指定唯一的bean注入。

    <context:annotation-config/>

    <bean id="people" class="People"/>
    <bean id="cat1" class="Cat"/>
    <bean id="cat2" class="Cat"/>
    <bean id="dog1" class="Dog"/>
    <bean id="dog2" class="Dog"/>


public class People {
    @Autowired
    @Qualifier(value = "cat1")
    private Cat cat;
    @Autowired
    @Qualifier(value = "dog1")
    private Dog dog;
......
}

@Resource 注解:

  • 默认通过byName实现,如果找不到,则通过byType实现
public class People {
    @Resource(name = "cat1")
    private Cat cat;
    
    @Autowired
    @Qualifier(value = "dog1")
    private Dog dog;
....
}

9、使用注解开发

使用注解开发需要导入AOP包,并在xml中增加context约束,开启注解的支持
在这里插入图片描述

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">


    <context:annotation-config/>

</beans>
  1. 装配bean
    <!--自动扫描包,将pojo包中的带有组件注解的类装配-->
    <context:component-scan base-package="com.pojo"/>
@Component
public class User {

    private String name;
  1. 属性的注入
@Component
public class User {

	//相当于<property name="name" value="张三"/>
    @Value("张三")
    private String name;
  1. @Component衍生的注解
    @Component 有几个衍生的注解,在web开发中会按照MVC三层架构分层

    • dao层:@Repository
    • service层:@Service
    • controller层:@Controller

    这四个注解的作用是一样的,都代表将某个类注册到spring中,装配bean

  2. 作用域

@Controller
//相当于<bean id="user" class="com.pojo.User" scope="prototype">
@Scope("prototype")
public class User {

    @Value("张三")
    private String name;
  1. 小结
    xml与注解:
    • xml更加万能,适用于任何场合,维护相对简单
    • 注解维护相对复杂
    • 最佳实践:xml用来管理bean,注解只负责属性的注入
    • 使用时要注意开启注解支持 <context:annotation-config/>

10、使用Java的方式配置spring

在spring boot中常用

java配置类:

@Configuration
public class MyConfig2 {

    @Bean
    @Scope("prototype")
    public Student getStudent(){
        return new Student();
    }
}
@Configuration
@ComponentScan("com.pojo")
@Import(MyConfig2.class)
public class MyConfig {

    @Bean
    public User user(){
        return new User();
    }

}

实体类:

@Component
public class User {

    @Value("张三")
    private String name;

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

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

@Component
public class Student {

    @Value("18")
    private int age;

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

测试:

public class Test04 {

    @Test
    public void test(){
    //使用Java配置类的方式,就只能通过AnnotationConfigApplicationContext来获取容器,通过配置类的class对象加载
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);

        User user = context.getBean("user",User.class);
        System.out.println(user);

        Student student1 = (Student) context.getBean("getStudent");
        Student student2 = (Student) context.getBean("getStudent");

        System.out.println(student1==student2); //false
    }
}






以上来自看kuangshen视频的笔记
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring是一个开源的Java框架,用于构建企业级应用程序。它提供了一种轻量级的、非侵入式的开发方式,通过依赖注入和面向切面编程等特性,简化了Java应用程序的开发过程。 以下是关于Spring学习的一些笔记: 1. IoC(控制反转):Spring通过IoC容器管理对象的创建和依赖关系的注入。通过配置文件或注解,将对象的创建和依赖关系的维护交给Spring容器来管理,降低了组件之间的耦合度。 2. DI(依赖注入):Spring通过依赖注入将对象之间的依赖关系解耦。通过构造函数、Setter方法或注解,将依赖的对象注入到目标对象中,使得对象之间的关系更加灵活和可维护。 3. AOP(面向切面编程):Spring提供了AOP的支持,可以将与业务逻辑无关的横切关注点(如日志、事务管理等)从业务逻辑中分离出来,提高了代码的可重用性和可维护性。 4. MVC(模型-视图-控制器):Spring提供了一个MVC框架,用于构建Web应用程序。通过DispatcherServlet、Controller、ViewResolver等组件,实现了请求的分发和处理,将业务逻辑和视图展示进行了分离。 5. JDBC和ORM支持:Spring提供了对JDBC和ORM框架(如Hibernate、MyBatis)的集成支持,简化了数据库访问的操作,提高了开发效率。 6. 事务管理:Spring提供了对事务的支持,通过声明式事务管理和编程式事务管理,实现了对数据库事务的控制和管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值