Spring:对bean的一种封装,以后拿对象不要new了。Spring是一个项目管理框架,同时也是一套Java EE解决方案。
核心模块主要包括:IOC,AOP,事物的统一管理三方面
spring 的使用方法;
1,首先要会搭建一个工厂;
工厂就是生产类的所以先定义一些类。可以在类里面定义一些方法,
2,配置依赖;
这一个依赖包含spring所有的依赖,maven的依赖具有传递性。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qf</groupId>
<artifactId>spring1</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- Spring常用依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<!-- main方法的测试包就不要写main方法了-->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!-- 生命周期 -->
<!-- 测试出结果为了不占用资源就不用test,不想要的测试就不要写test-->
<scope>test</scope>
</dependency>
</dependencies>
</project>
3,配置spring-config.xml文件;
定义要生产的对象。
标签遵循Schema规范才能被解析。
<?xml version="1.0" encoding="UTF-8"?>
<!--beans是根标签,用来声明这是一个装很多bean的容器
xmlns语义化标签所在的命名空间,就是定义改文件中标签的含义
xmlns:xsi:XMLSchema-instance 标签遵循Schema标签标准。
xsi:schemaLocation:xsd文件位置,用以描述标签语义、属性、取值范围等。
-->
<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="userDAO" class="com.qf.dao.UserDAOImpl"></bean>
<bean id="userService" class="com.qf.service.UserServiceImpl"></bean>
<!-- bean:代表一个对象;
id:唯一标识符(相当于键)
class:表示给对象所属类的全限路径名=包名+类名-->
</beans>
4,写测试类;
根据ApplicationContext启动工厂,然后通过bean获取对象。
public class SpringFactory {
@Test
public void testSpringFactory(){
//启动工厂(从xml里面拿id)
ApplicationContext context = new ClassPathXmlApplicationContext("/spring-config.xml");
//获取对象
UserDAO userDAO = (UserDAO) context.getBean("userDAO");//一定要向下专型
UserService userService = (UserService) context.getBean("userService");
userDAO.delereUser(1);//
userService.delereUser(2);
}
}
IOC(Inversion of Control )控制反转(十分重要:主要吧dao,service,等方法类放到IOC,model和util等不要放进去仓库)
含义:原来我们需要对象,我们都是自己手动的去new对象(控制权在使用者手里)
作用:ioc:将对象放到一个容器中,谁想用,则容器主动的将对象分配给他(对象的控制权将会反转给容器。
反转了依赖关系的满足方式,由之前的自己创建依赖对象,变为由工厂推送。(变主动为被动,即反转)
解决了具有依赖关系的组件之间的强耦合,使得项目形态更加稳健
控制反转只是思想层面的理解,要想完成反转就要靠一次又一次的DI(依赖注入)
项目中强耦合问题
所谓的强耦合就是serviceimpl和daoimpl的绑定关系,在我们实现逻辑类serviceimpl时,必须要绑定对相应的接口类dao实现对应的daoimpl,每次要想实现不同的daoimpl的就必须修改对应的serviceimpl,这样在做大型项目时就浪费了大量的资源,增加维护成本,解决思路是修改一个对应的不需要改变。所有通过在实现里定义一个接口,加一个get、set方法用以去获取要实现的方法。代码如下:
1,强耦合现象
public class UserDAOImpl implements UserDAO{....}
public class UserServiceImpl implements UserService {
// !!!强耦合了UserDAOImpl!!!,使得UserServiceImpl变得不稳健!!
private UserDAO userDAO= new UserDAOImpl();
@Override
public User queryUser() {
return userDAO.queryUser();
}
....
}
2,解决办法
// 不引用任何一个具体的组件(实现类),在需要其他组件的位置预留存取值入口(set/get)
public class UserServiceImpl implements UserService {
// !!!不再耦合任何DAO实现!!!,消除不稳健因素!!
private UserDAO userDAO;
// 为userDAO定义set/get,允许userDAO属性接收spring赋值
//Getters And Setters
@Override
public User queryUser() {
return userDAO.queryUser();
}
public UserDAO getUserDAO() {
return userDAO;
}
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
}
....
}
config。xml中也要加上dao的属性名(通过get/set方法去得到值)
DI(Dependency Injection)依赖注入
概念:在Spring创建对象的同时,为其属性赋值,称之为依赖注入。
1,set注入;原理就是调用set方法实现的;
分为:集合,自建属性,map集合
(看有没有赛进去值可以在test里加sout加断点,控制台查看)
<?xml version="1.0" encoding="UTF-8"?>
<!--beans是跟标签,用来声明这是一个装很多bean的容器
xmlns语义化标签所在的命名空间,就是定义改文件中标签的含义
xmlns:xsi:XMLSchema-instance 标签遵循Schema标签标准。不同的标签决定不同的作用
xsi:schemaLocation:xsd文件位置,用以描述标签语义、属性、取值范围等。
-->
<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:唯一标识符(相当于键)
class:表示给对象所属类的全限路径名=包名+类名-->
<!--bean定义要工厂生产的对象-->
<bean id="userDAO" class="com.qf.dao.UserDAOImpl"></bean>
<!-- 想要Mydao运作只要改一下id和对应的ref(只修改了新加的类和工厂的配置)-->
<bean id="userDAO2" class="com.qf.dao.MyUserDao"></bean>
<bean id="userService" class="com.qf.service.UserServiceImpl">
<!--如何给bean的属性赋值?
方法1:通过构造方法(constructor-arg标签)
name:构造方法的形参名(也就是set的形参)
value:给简单类型赋值(八大基本数据和String)
ref:给引用数据类型赋值,引用数据类型就是对象,由于只要是对象就交给容器控制
所以ref就是该对象在容器的id
如果引用数据类型是容器(list,map,set)
方法2:set注入(property标签)
name:形参名
value:给简单类型赋值(八大基本数据和String)日期用'/'
bean:直接给应用数据类型赋值-->
<property name="userDAO" ref="userDAO2"/>
<!-- 为userDAO的属性赋值(所以要有getset方法),值是id为userDAO的一个bean就是指 <bean id="userDAO" -->
</bean>
<!--自建属性:一定先bean出一个工厂对象才能注入user里-->
<bean id="addr" class="com.qf.entity.Address">
<property name="id" value="1"/>
<property name="city" value="bj"/>
</bean>
<!-- set注入(为user的属性赋值,===所以要有set方法用于注入时调用)-->
<bean id="user" class="com.qf.entity.User">
<property name="id" value="10"/>
<property name="password" value="123456"/>
<property name="sex" value="male"/>
<property name="age" value="19"/>
<property name="bornDate" value="2020/12/12"/>
<!-- 数组-->
<property name="hobbys">
<array>
<value>football</value>
<value>basketball</value>
</array>
</property>
<!-- 结合-->
<property name="names">
<list>
<value>tom</value>
<value>jack</value>
</list>
</property>
<!-- set集合-->
<property name="phones">
<set>
<value>1725648463</value>
<value>1736484737</value>
</set>
</property>
<!-- map集**合-->
<property name="countries">
<map>
<entry key="zh" value="chaina"></entry>
<entry key="en" value="english"></entry>
</map>
</property>
<!-- 文件注入-->
<property name="files">
<props>
<prop key="url">jdbc:mysql:111</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
<!-- 自建属性:相当于引用数据类型;当对象处理-->
<property name="address" ref="addr"></property>
</bean>
</beans>
2,构造注入
就是调用构造方法
必须是有参
<!-- 构造注入 (就是走构造方法)-->
<bean id="student" class="com.qf.entity.Student">
<constructor-arg name="id" value="1"/>
<constructor-arg name="name" value="wjl"/>
<constructor-arg name="sex" value="male"/>
<constructor-arg name="age" value="19"/>
</bean>
3,自动注入(了解)
不用在配置中 指定为哪个属性赋值,及赋什么值.
由spring自动根据某个 “原则” ,在工厂中查找一个bean,为属性注入属性值。
<bean id="userDao" class="com.qf.spring.part1.injection.UserDaoImpl" />
<!-- 为UserServiceImpl中的属性基于类型自动注入值 -->
<bean id="userService" class="com.qf.spring.part1.injection.UserServiceImpl" autowire="byType"></bean>
<bean id="userDao" class="com.qf.spring.part1.injection.UserDaoImpl" />
<!-- 为UserServiceImpl中的属性基于类型自动注入值 -->
<bean id="userService" class="com.qf.spring.part1.injection.UserServiceImpl" autowire="byName"></bean>