引入
程序的耦合:
程序间的依赖关系:类之间的依赖,方法之间的依赖
解耦合:降低程序间的依赖关系(尽量做到编译器不依赖,运行时才依赖)
解耦方式:
- 使用反射创建类对象,避免使用new关键字
- 通过读取配置文件来获取要创建的对象全限定类名
Spring基于XML的开发
1.导入坐标依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
2.编写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
https://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
3.导入Spring的配置文件
ApplicationContext的三个实现类:
- ClassPathXmlApplicationContext:
- FileSystemXmlApplicationContext:
- AnnotationConfigApplicationContext:
4.Spring的依赖注入
-
构造函数注入:
标签:constructor-arg
标签出现的位置:bean标签的内部
常用标签的属性:
(1)name:给指定构造函数中指定名称的参数赋值
(2)value:用于提供基本类型和String类型的数据
(3)ref:用于指定其他的bean类型数据。它指的是在Spring的IOC核心容器中出现过的bean对象
<bean id="accountService" class="com.service.Impl.AccountImpl"> <constructor-arg name="name" value="张三"></constructor-arg> <constructor-arg name="age" value="20"></constructor-arg> <constructor-arg name="birthday" ref="now"></constructor-arg> </bean>
package com.service.Impl; import com.Dao.IAccountDao; import com.Dao.Impl.AccountDaoImpl; import com.service.IAccountService; import java.text.DateFormat; import java.util.Date; public class AccountImpl implements IAccountService { private String name; private int age; private Date birthday; public AccountImpl(String name, int age, Date birthday) { this.name = name; this.age = age; this.birthday = birthday; } public void SaveAccount() { System.out.println(this.name + " " + this.age + " "+ this.birthday); } }
主方法测试
package com; import com.service.IAccountService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Demo { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); IAccountService as = (IAccountService) ac.getBean("accountService"); as.SaveAccount(); } }
-
set方法注入
标签:property
出现位置:bean标签内部
标签的属性:
(1)name:用于指定注入时所调用的set方法名称(去掉前面的Set然后小写)
(2)value:用于提供基本类型和String类型的数据
(3)ref:用于指定其他的bean类型数据。它指的是在Spring的IOC核心容器中出现过的bean对象,该数据类型需要先注入,然后在其他数据类型中通过,id注入。
3.注解方法注入
下面详细介绍
5.Spring复杂数据类型的注入
- List集合注入的标签:list,array,set
- Map集合注入的标签:map,props
Spring基于注解的开发
1.创建对象的注解
Tip:首先要在XML配置文件中扫描注解
<context:component-scan base-package="被扫描的包名"></context:component-scan>
-
@Component:将当前类对象存入Spring容器
属性:value:指定bean的id(默认id为首字母小写的类名)
-
@Controller(表现层),@Service(业务层)@Repository(持久层):这三个注解功能与属性与@Component一致,只是Spring框架提供的明确的三层架构
2.注入数据的注解
-
@Autowirted:自动按照类型注入
对于Autowirted,注入时必须使用已经存在bean,如果同时存在两个实现类继承了一个接口,需要使用@Qualifier进行区分,或者根据类名进行区分
-
@Qualifier:在原注入基础上根据名称注入
属性:value 用于指定
-
@Resource:直接根据bean的id注入
属性:name用于指定bean的id
-
@Value:用于注入基本数据类型和String类型
属性:value用于指定数据的值
3.改变作用范围的注解
-
@Scope
属性:value用于指定范围取值(singleton[单例],prototype[多例])
Spring基于XML的开发案例
利用Spring使用JDBC以及Druid代理池,实现对数据库的增删查改
依赖导入
<?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>org.example</groupId>
<artifactId>SpringDay02</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.23</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
</dependencies>
</project>
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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 配置Service -->
<bean id="accountService" class="com.Service.Impl.AccountServiceImpl">
<!--通过set方法注入accountDao -->
<property name="accountDao" ref="accountDao"></property>
</bean>
<!--配置Dao-->
<bean id="accountDao" class="com.Dao.Impl.AccountDaoImpl">
<!--通过set方法注入JdbcTemplate-->
<property name="jt" ref="jt"></property>
</bean>
<!--配置JdbcTemplate-->
<bean id="jt" class="org.springframework.jdbc.core.JdbcTemplate">
<!--由于JdbcTemplate不提供set方法,所以这里提供构造方法注入dataSource-->
<constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
</bean>
<!--配置DataSource-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!--注入mysql的用户名 密码 url 驱动-->
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///springdemo"></property>
<property name="username" value="root"></property>
<property name="password" value="sr20000316"></property>
</bean>
</beans>
对于Spring基于XML的配置可以分为以下几个步骤:
1、配置类
2、对该类中的数据进行注入,具体是注入方式详见最上方
Account实体
package com.Bean;
import java.io.Serializable;
public class Account implements Serializable {
private Integer id;
private String name;
private Integer 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 Integer getMoney() {
return money;
}
public void setMoney(Integer money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}
IAccountService接口
package com.Service;
import com.Bean.Account;
import java.util.List;
public interface IAccountService {
public List<Account> findall();
public Account findAccountById();
public void saveAccount(Account account);
public void updateAccount(Account account);
public void deleteAccount(Integer id);
}
IAccountService实现类
package com.Service.Impl;
import com.Bean.Account;
import com.Dao.IAccountDao;
import com.Service.IAccountService;
import java.util.List;
public class AccountServiceImpl implements IAccountService {
private IAccountDao accountDao;
public void setAccountDao(IAccountDao accountDao) {
this.accountDao = accountDao;
}
public List<Account> findall() {
return accountDao.findall();
}
public Account findAccountById() {
return accountDao.findAccountById();
}
public void saveAccount(Account account) {
accountDao.saveAccount(account);
}
public void updateAccount(Account account) {
accountDao.updateAccount(account);
}
public void deleteAccount(Integer id) {
accountDao.deleteAccount(id);
}
}
IAccountDao接口
package com.Dao;
import com.Bean.Account;
import java.util.List;
public interface IAccountDao {
public List<Account> findall();
public Account findAccountById(Integer id);
public void saveAccount(Account account);
public void updateAccount(Account account);
public void deleteAccount(Integer id);
}
IAccountDao接口实现类
package com.Dao.Impl;
import com.Bean.Account;
import com.Dao.IAccountDao;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.beans.BeanProperty;
import java.util.List;
public class AccountDaoImpl implements IAccountDao {
private JdbcTemplate jt;
public void setJt(JdbcTemplate jt) {
this.jt = jt;
}
public List<Account> findall() {
return jt.query("select* from account",new BeanPropertyRowMapper<Account>(Account.class));
}
public Account findAccountById(Integer id) {
Object[] params = {id};
List<Account> accounts = jt.query("select* from account where id = ?", params, new BeanPropertyRowMapper<Account>(Account.class));
return accounts.get(0);
}
public void saveAccount(Account account) {
Object[] params = {account.getId(),account.getName(),account.getMoney()};
jt.update("insert into account values(?,?,?)",params);
}
public void updateAccount(Account account) {
Object[] params = {account.getName(),account.getMoney(),account.getId()};
jt.update("update account set name = ?,money = ? where id = ?",params);
}
public void deleteAccount(Integer id) {
Object[] params = {id};
jt.update("delete from account where id = ?",params);
}
}
测试类
package com;
import com.Bean.Account;
import com.Service.IAccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class Demo {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
IAccountService as = (IAccountService) ac.getBean("accountService");
//删除操作
as.deleteAccount(2);
Account account = new Account();
account.setId(4);
account.setMoney(3000);
account.setName("王五");
//新增操作
as.saveAccount(account);
//查找所有操作
List<Account> accounts = as.findall();
System.out.println(accounts);
Account account2 = new Account();
account2.setId(1);
account2.setName("张三");
account2.setMoney(30000);
as.updateAccount(account2);
//根据ID查找操作
Account account1 = as.findAccountById(1);
System.out.println(account1);
}
}
Spring基于注解的开发案例
依赖注入
<?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>org.example</groupId>
<artifactId>SpringDay02</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.23</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
</dependencies>
</project>
IAccountService接口
package com.Service;
import com.Bean.Account;
import java.util.List;
public interface IAccountService {
public List<Account> findall();
public Account findAccountById(Integer id);
public void saveAccount(Account account);
public void updateAccount(Account account);
public void deleteAccount(Integer id);
}
IAccountService实现类
package com.Service.Impl;
import com.Bean.Account;
import com.Dao.IAccountDao;
import com.Service.IAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service("accountService")
public class AccountServiceImpl implements IAccountService {
@Autowired
private IAccountDao accountDao;
public void setAccountDao(IAccountDao accountDao) {
this.accountDao = accountDao;
}
public List<Account> findall() {
return accountDao.findall();
}
public Account findAccountById(Integer id) {
return accountDao.findAccountById(id);
}
public void saveAccount(Account account) {
accountDao.saveAccount(account);
}
public void updateAccount(Account account) {
accountDao.updateAccount(account);
}
public void deleteAccount(Integer id) {
accountDao.deleteAccount(id);
}
}
IAccountDao接口
package com.Dao;
import com.Bean.Account;
import java.util.List;
public interface IAccountDao {
public List<Account> findall();
public Account findAccountById(Integer id);
public void saveAccount(Account account);
public void updateAccount(Account account);
public void deleteAccount(Integer id);
}
IAccountDao实现类
package com.Dao.Impl;
import com.Bean.Account;
import com.Dao.IAccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {
@Autowired
private JdbcTemplate jt;
public List<Account> findall() {
return jt.query("select* from account",new BeanPropertyRowMapper<Account>(Account.class));
}
public Account findAccountById(Integer id) {
Object[] params = {id};
List<Account> accounts = jt.query("select* from account where id = ?", params, new BeanPropertyRowMapper<Account>(Account.class));
return accounts.get(0);
}
public void saveAccount(Account account) {
Object[] params = {account.getId(),account.getName(),account.getMoney()};
jt.update("insert into account values(?,?,?)",params);
}
public void updateAccount(Account account) {
Object[] params = {account.getName(),account.getMoney(),account.getId()};
jt.update("update account set name = ?,money = ? where id = ?",params);
}
public void deleteAccount(Integer id) {
Object[] params = {id};
jt.update("delete from account where id = ?",params);
}
}
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"
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:component-scan base-package="com"></context:component-scan>
<bean id="jt" class="org.springframework.jdbc.core.JdbcTemplate">
<!--由于JdbcTemplate不提供set方法,所以这里提供构造方法注入dataSource-->
<constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
</bean>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!--注入mysql的用户名 密码 url 驱动-->
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///springdemo"></property>
<property name="username" value="root"></property>
<property name="password" value="sr20000316"></property>
</bean>
</beans>
Spring的配置类
从上面的基于注解实现的IOC案例中,可以发现,虽然使用注解创建了对象,但是我们仍然需要配置文件来创建那些不是我们自己写的类,所以这里就再次引入三个注解,这样就可以在使用注解时完全脱离XML配置文件
-
@Configuration:指定当前类为一个配置类
-
@ComponentScan:通过注解指定Spring的创建容器中要扫描的包
属性:value/basePackages:扫描某一个包 下的全部注解
-
@bean:用于把当前方法的返回值作为bean对象存入Spring的IOC容器中
-
@Import:
属性:value:导入其他的配置类,有Import注解的类是主配置类
-
@PropertySource
属性:value:指定文件的名称和路径;classpath表示类路径下
package com.Config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
@Configuration
@ComponentScan("com")
public class SpringConfiguration {
@Bean(name = "jdbc")
public JdbcTemplate creatJDBC(DataSource ds){
return new JdbcTemplate(ds);
}
@Bean(name = "dataSource")
public DataSource createDateSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUsername("root");
ds.setPassword("sr20000316");
ds.setUrl("jdbc:mysql:///springdemo");
return ds;
}
}
当使用上面的三个注解以后,我们就可以完全脱离XML配置文件了,这里测试方法中要读取这个类
f恩别package com;
import com.Bean.Account;
import com.Config.SpringConfiguration;
import com.Service.IAccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class Demo {
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
IAccountService as = (IAccountService) ac.getBean("accountService");
//删除操作
// as.deleteAccount(2);
Account account = new Account();
account.setId(4);
account.setMoney(3000);
account.setName("王五");
//新增操作
as.saveAccount(account);
//查找所有操作
List<Account> accounts = as.findall();
System.out.println(accounts);
Account account2 = new Account();
account2.setId(1);
account2.setName("张三");
account2.setMoney(30000);
as.updateAccount(account2);
//根据ID查找操作
Account account1 = as.findAccountById(1);
System.out.println(account1);
}
}
实际开发中一般使用注解和XML混合使用
总结
在Spring中我们经常谈到注入的概念,这里的注入分为两种方式,一种是通过在xml文件中配置,一种是通过注解(bean),按照我的理解,注入其实就是,比如说你定义了一个对象Account account,通过注入的方式,Spring会知道你只要定义了这个Account,他就知道你使用的这个类型,不需要new,可以直接使用。但是这里要注意,如果有唯一匹配时,直接注入即可,但是如果有多个匹配,首先按照类型筛选出符合条件的对象,然后根据id(@bean(id)),分别匹配,如果有唯一对应就注入成功,否则注入失败