Spring基础学习
一、入门案例
通过spring创建对象
1、依赖包导入
2、创建User类对象
package com.atguigu.spring5;
//step4
public class User {
private String userName;
public void add(){
System.out.println("add...");
}
}
3、编写xml文件,添加bean标签
<bean id="user" class="com.atguigu.spring5.User"></bean>
4、编写测试代码
public class TestSpring5 {
@Test
// 加了@Test后,该函数就可以单独运行了.
public void testAdd(){
// 1.加载spring配置文件
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml" );
// 2.获取配置创建的对象
User user = context.getBean("user", User.class);
System.out.println(user);//完成了对象的创建
user.add();
}
二、IOC容器
*控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理
*使用IOC目的:为了耦合度降低
*底层原理:xml解析、工厂模式、反射
1、IOC过程
·第一步 xml配置文件,配置创建的对象
<bean id="dao" class="com.atguigu.UserDao"></bean>
·第二步 有service类和dao类,创建工厂类
2、Spring提供IOC容器实现两种方式:(两个接口)
a.BeanFactory
·加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用
b.ApplicationContext
·加载配置文件时候就会把配置文件对象进行创建
BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用
3、IOC操作bean管理
a.bean管理指的是两个操作
(1)Spring创建对象:
在bean标签中有很多属性,介绍常用的属性;id属性,唯一标识;class属性,类全路径(包类路径);name属性,与id属性类似,区别是name属性可以使用特殊符号,一般不使用这个属性,在spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建,创建对象时候,默认也是执行无参构造方法完成对象创建。
public class Book {
public void test(){
System.out.println(list);
}
}
@Test
public void testCollection2(){
ApplicationContext context =
new ClassPathXmlApplicationContext("bean.xml");
book.test();
}
<bean id="book" class="com.atguigu.spring5.collectiontype.Book" scope="prototype"></bean>
(2)属性注入:
Spring注入属性有xml方式和外部导入properties文件方式以及**注解注入等方式。(见第4小节)
4、属性注入
a.普通赋值
(1)xml方式
//通用测试代码
@Test
public void testOrders(){
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
Orders orders = context.getBean("orders", Orders.class);
System.out.println(orders);
orders.ordersTest();
}
①有参构造器注入-先在类中生成有参构造函数
public class Orders {
private String name;
private String address;
public Orders(String name, String address) {
this.name = name;
this.address = address;
}
public void ordersTest(){
System.out.println(this.name + "::" + this.address);
}
}
<bean id="orders" class="com.atguigu.spring5.Orders">
<constructor-arg name="name" value="电脑"></constructor-arg>
<constructor-arg name="address" value="China"></constructor-arg>
</bean>
②set注入-先在类中生成属性set方法
public class Orders {
private String name;
private String address;
public void setAddress(String address) {
this.address = address;
}
public void setName(String name) {
this.name = name;
}
public void ordersTest(){
System.out.println(this.name + "::" + this.address);
}
}
<bean id="orders" class="com.atguigu.spring5.Orders">
<property name="name" value="电脑"></property>
<property name="address" value="China"></property>
</bean>
③p注入(用的不多,用时即时百度)
④空值和特殊符号
<property name="address">
<null/>
</property>
<property name="address">
<value> <![CDATA[<<南京>>]]> </value>
</property>
(2)properties文件方式(数据库中会使用)–以配置德鲁伊连接池为例
①导包
②配置演示
直接配置:
<bean id="DataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/userDb"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
外部文件引入配置:
#jdbc.properties文件
prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/userDb
prop.userName=root
prop.password=root
<!--需添加context命名空间
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="DataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${prop.driverClass}"></property>
<property name="url" value="${prop.url}"></property>
<property name="username" value="${prop.userName}"></property>
<property name="password" value="${prop.password}"></property>
(3)注解注入方式
①半注解方式(需要有xml文件存在)
<!--同样要先添加context命名空间,添加方式如(2)-->
<!--<context:component-scan base-package="com.atguigu.spring5.dao,com.atguigu.spring5.service"></context:component-scan>-->
<context:component-scan base-package="com.atguigu.spring5"></context:component-scan>
<!--示例1
use-default-filters="false" 表示现在不适用默认filter,自动配置filter
context:include-filter,设置扫描哪些内容-->
<!--
<context:component-scan base-package="com.atguigugu" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
-->
<!--示例2
use-default-filters="false" 表示现在不适用默认filter,自动配置filter
context:include-filter,设置哪些内容不扫描
-->
<!--
<context:component-scan base-package="com.atguigugu" use-default-filters="false">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
-->
Spring针对Bean管理中创建对象提供注解(下面四个功能都一样,实际开发中根据名称将其用在不同的层次中)
@component
@Controller
@Repository
@Service
@Component
public interface UserDao {
public void add();
}
@Repository(value="userDaoImp1")
//相当于配置了<bean id="userDaoImpl" class="import org.springframework.stereotype.Component.UserDaoImpl"</bean>
public class UserDaoIml implements UserDao {
@Override
public void add() {
System.out.println("dao add .....");
}
}
Spring针对Bean管理中属性注入提供注解
首先导入jar包:import org.springframework.beans.factory.annotation
@Autowired:根据属性类型进行自动装配,需.Autowired;
@Service //创建对象
public class UserService {
//不需要添加set方法,添加注入属性注解
@Autowired //根据类型注入对象
private UserDao userDao; //用接口定义属性,Autowired会自动寻找其实现类(注入)对其创建
public void add(){
System.out.println("service add ....");
System.out.println(name);
userDao.add(); //此能方法执行,说明userDao已经注入成功
}
}
@Qualifier:根据属性名称进行注入,该注解要和Autowired一起使用(当一个接口有多个实现类的时候,其可指定某个实现类,推荐使用)
@Qualifier(value = "userDaoImp1")
//value的值:该值和实现类 创建时候bean中的id保持一致,或是@Repository(value="userDaoImp1")中的value值保持一致
private UserDao userDao;
@Resource:可以根据类型注入,也可以根据名称注入;需另外import javax.annotation.Resource;
@Resource //按类名注入
@Resource(value = "UserDaoImpl1")//根据名称进行注入
private UserDao userDao;
@Value:注入普通类型(String,…)
@Value(value = "abc")
private String name;
//name = "abc"
②完全注解方式
@Configuration //作为配置类,替代配置文件
@ComponentScan(basePackages = {"com.atguigu"})
//相当于之前的<context:component-scan base-package="com.atguigu"></context:component-scan>
public class SpringConfig {
}
@Test
public void testService2() {
ApplicationContext context
= new AnnotationConfigApplicationContext(SpringConfig.class);//此处较之前做了修改
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService);
userService.add();
}
b.级联赋值
(1)内部bean方式
<bean id="emp" class="com.atguigu.spring5.bean.Emp">
<property name="ename" value="lucy"></property>
<property name="gender" value="女"></property>
<property name="dept">
<bean id="dept" class="com.atguigu.spring5.bean.Dept">
<property name="dname" value="安保部"></property>
</bean>
</property>
</bean>
(2)外部bean方式
<bean id="emp" class="com.atguigu.spring5.bean.Emp">
<property name="ename" value="lucy"></property>
<property name="gender" value="女"></property>
<property name="dept" ref="dept1"> </property>
</bean>
<bean id="dept1" class="com.atguigu.spring5.bean.Dept">
<property name="dname" value="安保部"></property>
</bean>
(3)使用util实现封装使用
<!--需添加util命名空间
xmlns:util="http://www.springframework.org/schema/util"
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
-->
<util:list id="bookList">
<value>西游记</value>
<value>三国演义</value>
<value>水浒传</value>
</util:list>
<bean id="book" class="com.atguigu.spring5.collectiontype.Book" scope="prototype">
<property name="list" ref="bookList"></property>
</bean>
c.自动装配
autowire属性常用的两个值:
byName根据属性名称注入 要求注入值bean的id值和类中属性名称一样
byType根据属性类型注入 即根据class值匹配类来自动注入 不能注入多个
<bean id="emp" class="com.atguigu.spring5.autowrite.Emp" autowire="byName"></bean>
<!-- <bean id="emp" class="com.atguigu.spring5.autowrite.Emp" autowire="byType"></bean> -->
5、几个概念
a.工厂bean
判断:通过比较bean定义时候的类和返回时候(使用)的类是否相同,不同则为工厂bean;反之为普通bean。
<bean id="myBean" class="com.atguigu.spring5.factorybean.MyBean"></bean>
public class MyBean implements FactoryBean<Course> {
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setCname("计算机组成原理");
return course;
}
...
}
@Test
public void testCollection3(){
ApplicationContext context =
new ClassPathXmlApplicationContext("bean3.xml");
Course course = context.getBean("myBean",Course.class);
//定义的类型与返回的类型不一样,定义的是MyBean,用的却是Course,这就是工厂bean
//理解:在bean中定义一个早餐店的工厂,而解析使用的类(返回过来的)可以是早餐店1,早餐店2...;
System.out.println(course);
}
b.bean的生命周期
第一步:通过构造器创建bean实例
第二步:为bean的属性设置值和对其他bean引用
在初始化之前执行的方法
第三步:执行初始化的方法
在初始化之后执行的方法
第四步:获取创建bean实例对象
第五步:执行销毁的方法
public class Orders {
//无参构造
public Orders() {
System.out.println("第一步:通过构造器创建bean实例");
}
private String oname;
public void setOname(String oname) {
this.oname = oname;
System.out.println("第二步:为bean的属性设置值和对其他bean引用");
}
//创建执行初始化的方法
public void initMethod(){
//此步骤需要在配置文件bean中配置执行
System.out.println("第三步:执行初始化的方法");
}
//创建执行销毁的方法
public void destroyMethod(){
//此步骤需要在配置文件bean中配置执行
System.out.println("第五步:执行销毁的方法");
}
}
public class MyBeanPost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之前执行的方法");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之后执行的方法");
return bean;
}
}
@Test
public void testBean4(){
//演示bean的生命周期
//ApplicationContext context =
// new ClassPathXmlApplicationContext("bean4.xml");
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("bean4.xml");
Orders orders = context.getBean("orders",Orders.class);
System.out.println("第四步:获取创建bean实例对象");
System.out.println(orders);
<bean id="orders" class="com.atguigu.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
<property name="oname" value="手机"></property>
</bean>
<!--配置后置处理器-->
<!--这样配置以后会为 此配置文件 中的所有bean都会配置上后置处理器,即会执行初始化前后的方法-->
<bean id="myBeanPost" class="com.atguigu.spring5.bean.MyBeanPost"></bean>
尚硅谷课程Spring5的课堂笔记