Spring

Spring

基本概念

Spring 是一个开源的、轻量级的 Java 企业级应用开发框架

  • 控制反转(IoC):是一种设计思想,将对象的创建和依赖关系的管理从程序代码转移到外部容器,由容器来负责创建对象、管理对象的生命周期以及对象之间的依赖关系。
  • 依赖注入(DI):是控制反转的一种实现方式,通过在对象创建时或运行时将依赖对象注入到目标对象中,使得目标对象不需要主动去创建或查找依赖对象,从而实现对象之间的解耦。
  • 面向切面编程(AOP):是一种编程范式,它允许将与业务逻辑无关的横切关注点(如日志记录、事务管理、安全检查等)从业务逻辑中分离出来,以独立的切面形式进行模块化管理,提高代码的复用性和可维护性。
  • Spring 容器:是 Spring 框架的核心,用于管理和配置应用程序中的对象。它负责对象的创建、初始化、装配和销毁等生命周期管理,主要有 BeanFactory 和 ApplicationContext 两种类型。
  • Bean:在 Spring 中,由 Spring 容器管理的对象称为 Bean。可以通过配置文件或注解等方式将普通的 Java 对象定义为 Bean,使其能够享受 Spring 容器提供的各种服务。

作用

  • 解耦和降低耦合度:通过 IoC 和 DI 机制,使得组件之间的依赖关系更加松散,降低了代码之间的耦合度,提高了代码的可维护性和可扩展性。
  • 提高代码复用性:AOP 的应用使得横切关注点能够以切面的形式进行复用,避免了在多个业务逻辑中重复编写相同的代码。
  • 简化开发流程:提供了一系列的功能和工具,如数据访问、事务管理、Web 开发等,简化了企业级应用开发的流程,提高了开发效率。
  • 方便的配置管理:可以通过配置文件或注解等方式对 Bean 进行灵活的配置,方便地修改和调整应用程序的行为和参数。

应用场景

  • 企业级应用开发:适用于构建各种规模的企业级应用,如电子商务系统、企业资源规划(ERP)系统、客户关系管理(CRM)系统等,满足企业级应用对高可维护性、高可扩展性和高性能的要求。
  • Web 应用开发:在 Web 应用开发领域,Spring 提供的 Spring MVC 等框架为构建 Web 应用提供了便捷的方式,能够快速开发出功能强大、用户体验良好的 Web 应用程序。
  • 微服务架构:在微服务架构中,Spring Boot 等相关技术为微服务的快速开发和部署提供了有力支持,方便地构建独立、可扩展和易于维护的微服务。
  • 大数据和云计算:Spring 也在大数据和云计算领域有着广泛的应用,如与 Hadoop、Spark 等大数据框架的集成,以及在云计算平台上的部署和运行等。

优势

  • 提高开发效率:通过提供丰富的功能和便捷的开发方式,减少了开发者编写大量重复代码的工作量,从而加快了项目的开发进度。
  • 增强代码质量:其设计模式和架构理念有助于编写结构清晰、易于维护和扩展的代码,降低了代码的耦合度,提高了代码的可读性和可测试性。
  • 跨平台和兼容性:Spring 具有良好的跨平台性,能够在不同的操作系统和应用服务器上运行,并且与各种开源和商业的技术框架和工具具有良好的兼容性。
  • 社区支持和开源生态:拥有庞大而活跃的社区,开发者可以在社区中获取丰富的技术资源、文档、教程和开源库,同时也可以积极参与社区贡献,分享自己的经验和代码。

IoC容器

首先了解项目的结构

//我们项目拥有两个包,分别是service和dao,其下分别拥有一个接口和一个实现类,Service依赖Dao
public interface BookService{
	public void save();
}
public class BookServiceImpl implements BookService {
    private BookDao bookDao = new BookDaoImpl();
    public void save(){
        System.out.println("BookService Run !");
        bookDao.save();
    }
}

public interface BookDao{
	public void save();
}
public class BookDaoImpl implements BookDao {
	public void save(){
		System.out.println("BookDao Run !");
	}
}

此处使用传统的配置文件方法来将依赖放到IoC容器中。

第一步:导入Spring坐标

既然要使用Spring,首先应该导入其坐标

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>5.2.10.RELEASE</version>
</dependency>

第二步:创建配置文件

我们需要创建Spring配置文件,配置对应的类作为Spring管理的Bean

resources配置文件夹下声明Spring的配置类 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       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-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
    
</beans>

第三步:配置bean

在上面配置类模板中,添加如下配置,用来配置哪些类是被Spring管理的bean

<!--bean标签配置Bean
	id属性给bean起名
	class属性给bean定义类型
-->
<!--注意一定要配置实现类-->
<bean id="bookDao" class="com.angelday.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.angelday.service.impl.BookServiceImpl"/>

配置项:

  • id 属性
    • 用于用于为该bean定义一个唯一的标识符。在整个 Spring 容器的配置范围内,id的值必须是唯一的,不能与其他beanid重复。
    • 它主要用于在其他地方引用该bean,例如通过@Autowired注解注入依赖时,就是根据beanid或其默认名称(如果没有显式指定id)来查找对应的bean实例并注入到目标对象中的。
    • 可以将其理解为一个对象在 Spring 容器中的 “名字”,通过这个 “名字”,Spring 能够准确地找到并管理对应的对象实例。
  • class属性
    • 用于指定要实例化的类的全限定名,包括包名和类名。
    • Spring 会根据这个全限定名,使用反射机制来创建该类的实例,并将其作为一个bean对象管理在容器中。
    • 它告诉 Spring 具体要创建哪种类型的对象,以便 Spring 能够正确地进行实例化、初始化以及依赖注入等操作。

第四步:获取IoC容器

在程序的启动类中获取IoC容器

public class App {
    public static void main(String[] args){
        //获取IoC容器
        //注意需要将配置文件作为参数放入该构造方法中
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    }
}

第五步:获取Bean

public class App {
    public static void main(String[] args){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取Bean
        //注意该方法需要将bean的名称作为参数传入
        //并且该方法返回值为Object
        Object bean = ctx.getBean("bookDao");
        //所以需要强转换为BookDao类型
        BookDao bookDao = (BookDao)bean;
        
        //获取bean之后就可以使用了
        bookDao.save();
    }
}

通过以上步骤,我们成功地使用传统的配置文件方法将项目中的依赖放入了 Spring 的 IoC 容器中。这种方式为我们的项目带来了更好的结构和可维护性,使得对象之间的依赖关系更加清晰明了。然而,这仅仅是 Spring 强大功能的一部分。在接下来的章节中,我们将深入探讨 Spring 的依赖注入(DI)机制,了解它如何进一步优化我们的代码结构,提高开发效率,并实现更加灵活的应用程序设计。

DI

依赖注入,作为一种强大的设计理念和技术手段,在 Java 应用开发中发挥着至关重要的作用。它能够有效地降低代码之间的耦合度,使得各个模块之间的依赖关系更加清晰、易于管理。通过 DI,我们不再需要在对象内部手动创建其依赖的对象,而是由外部容器负责将所需的依赖对象注入到目标对象中。

删除 new 的方式

竟然知道不需要自己通过new 来创建对象,所以我们需要先吧业务代码中new的部分删除
提供一个setter方法

public class BookServiceImpl implements BookService {
    
    //private BookDao bookDao = new BookDaoImpl();
    private BookDao bookDao;
    
    public void save(){
        System.out.println("BookService Run !");
        bookDao.save();
    }

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}

修改配置文件

我们需要告诉Spring,需要把Dao放到Service当中,所以我们需要修改bean的定义

<bean id="bookDao" class="com.angelday.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.angelday.service.impl.BookServiceImpl">
    <!-- 配置Service与Dao的关系 -->
    <!-- property标签长不魔置当前bean的属性
        name属性表示配置哪一个具体的属件
        ref属性表示参照哪一个bean
    -->
    <property name="bookDao" ref="bookDao"/>
</bean>

注意:

  • property 标签:在 Spring 配置文件中,<property>标签用于设置 Bean 的属性值。在这里,它用于设置BookServiceImplbookDao属性。
  • name属性:<property>标签的name属性指定了要设置的属性名称,这里是bookDao,它必须与BookServiceImpl类中定义的BookDao类型的属性名称完全一致。
  • ref属性:<property>标签的ref属性用于指定要注入的另一个 Bean 的引用,这里的值是bookDao,它对应着前面配置的BookDao的< bean>标签的id属性,通过这种方式,Spring 容器会将id为bookDao的Bean实例注入到BookServiceImpl的bookDao属性中。

此时再运行main方法,发现代码任然正常运行,说明dao成功注入到service中

依赖注入

四种注入方式

前面说到将Dao注入到Service中,我们没有采用new的方式,而是使用了Setter方法。
其实向一个类中传递数据,拥有两种方式

  • 普通方法(set)
  • 构造方法

依赖注入描述了容器中建立的bean与bean之间的依赖关系,传输数据我们可以分为两类

  • 引用类型
  • 简单类型(基本数据类型与String)

根据上面我们可以分为四种依赖注入方式

  • setter注入
    • 简单类型
    • 引用类型
  • 构造器注入
    • 简单类型
    • 引用类型

setter注入-引用类型

前面使用的方式就是这种方法,首先再bean中定义set方法,在配置中添加property标签,注入引用数据类型。

public class BookServiceImpl implements BookService {
    
    private BookDao bookDao;
    
    public void save(){
        System.out.println("BookService Run !");
        bookDao.save();
    }

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}
<bean id="bookDao" class="com.angelday.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.angelday.service.impl.BookServiceImpl">
    <property name="bookDao" ref="bookDao"/>
</bean>

setter注入-简单类型

public class BookServiceImpl {
    private int connectionNum;
    private String databaseName;

    public void setConnectionNum(int connectionNum) {
        this.connectionNum = connectionNum;
    }

    public void setDatabaseName(String databaseName) {
        this.databaseName = databaseName;
    }
}

此处配置文件略有不同

<bean id="bookDao" class="com.angelday.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.angelday.service.impl.BookServiceImpl">
    <property name="connectionNum" value="10"/>
    <property name="databaseName" value="mysql"/>
</bean>

注:前面我们知道ref属性表示参照哪一个bean,
由于此处是具体的值,所以使用value属性

构造器注入-引用类型

使用构造器注入我们就不需要Set方法了,写一个构造方法

public class BookServiceImpl implements BookService {
    
    private BookDao bookDao;
    
    //构造方法
    public BookServiceImpl(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    public void save(){
        System.out.println("BookService Run !");
        bookDao.save();
    }
}

并且配置文件中也不同

<bean id="bookDao" class="com.angelday.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.angelday.service.impl.BookServiceImpl">
    <!-- 此处的name为构造方法的参数名 -->
    <constructor-arg name="bookDao" ref="bookDao"/>
</bean>

配置细节

  • constructor-arg标签:在 Spring 配置文件中,<constructor-arg>标签专门用于向 Bean 的构造函数传递参数。在这里,它用于向BookServiceImpl的构造函数传递BookDao实例。
  • name属性:<constructor-arg>标签的name属性指定了构造函数中参数的名称,这里是bookDao,它必须与BookServiceImpl构造函数中定义的BookDao类型参数的名称完全匹配。
  • ref属性:与<property>标签中的ref属性作用类似,这里的ref属性指定了要注入的另一个 Bean 的引用,其值为bookDao,对应着前面配置的BookDao的<bean>标签的id属性。通过这种方式,Spring 容器会将idbookDaoBean实例作为参数传递给BookServiceImpl的构造函数。

构造器注入-简单类型

public class BookServiceImpl {
    private int connectionNum;
    private String databaseName;

    public BookServiceImpl(int connectionNum, String databaseName) {
        this.connectionNum = connectionNum;
        this.databaseName = databaseName;
    }
}
<bean id="bookService" class="com.angelday.service.impl.BookServiceImpl">
    <!-- 此处的name为构造方法的参数名 -->
    <property name="connectionNum" value="10"/>
    <property name="databaseName" value="mysql"/>
</bean>

了解内容

<?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-4.0.xsd">
    

    <!-- 此处的name名,必须为构造方法的形参名,提高了耦合,所以我们又另一种写法 -->
    <bean id="bookService" class="com.angelday.service.impl.BookServiceImpl">
        <!-- 此处的name为构造方法的参数名 -->
        <property name="connectionNum" value="10"/>
        <property name="databaseName" value="mysql"/>
    </bean>

    <!-- 此方法解决了名称的耦合度 -->
    <bean id="bookService" class="com.angelday.service.impl.BookServiceImpl">
        <!-- 此处的type为构造方法的数据类型 -->
        <property type="int" value="10"/>
        <property type="java.lang.String" value="mysql"/>
    </bean>

    <!-- 解决参数类型重复问题 -->
    <bean id="bookService" class="com.angelday.service.impl.BookServiceImpl">
        <!-- 此处的index为构造方法的参数的顺序 -->
        <property index="0" value="10"/>
        <property index="1" value="mysql"/>
    </bean>
</beans>

依赖注入方式选择

  1. 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致nu11对象出现
  2. 可选依赖使用setter注入进行,灵活性强
  3. Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
  4. 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
  5. 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
  6. 自己开发的模块推荐使用setter注入

自动装配(重要)

IoC容器根据bean所依赖的资源在容器中自动査找并注入到bean中的过程称为自动装配

自动装配方式

  • 按类型(主要)
  • 按名称
  • 按构造方法

第一步:方法提供构造方法。

public class BookServiceImpl implements BookService {
    
    private BookDao bookDao;
    
    public void save(){
        System.out.println("BookService Run !");
        bookDao.save();
    }

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}

第二步:删除自己写的注入,添加autowire属性

<bean id="bookDao" class="com.angelday.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.angelday.service.impl.BookServiceImpl" autowire="byType">
</bean>

依赖自动装配特征

  • 自动装配用于引用类型依赖注入,不能对简单类型进行操作
  • 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用
  • 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
  • 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效

集合注入

主要了解配置的格式

public class BookServiceImpl {

    private int[] array;
    private List<String> list;
    private Set<String> set;
    private Map<String,String> map;
    private Properties properties;

    public void setArray(int[] array) {
        this.array = array;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }
}
<?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-4.0.xsd">
    <bean id="bookService" class="com.angelday.service.impl.BookServiceImpl">
        <property name="array">
            <array>
                <value>100</value>
                <value>200</value>
                <value>300</value>
                <!-- 如果内容是引用类型则使用这种写法 -->
                <!-- 一般都是简单类型 -->
                <!-- <ref bean="beanId"/> -->
            </array>
        </property>

        <property name="list">
            <list>
                <value>angel</value>
                <value>day</value>
                <value>hello</value>
            </list>
        </property>

        <property name="set">
            <set>
                <value>angel</value>
                <value>day</value>
                <value>hello</value>
            </set>
        </property>

        <property name="map">
            <map>
                <entry key="country" value="china"/>
                <entry key="province" value="hebei"/>
                <entry key="city" value="handan"/>
            </map>
        </property>

        <property name="properties">
            <props>
                <prop key="country">china</prop>
                <prop key="province">hebei</prop>
                <prop key="city">handan</prop>
            </props>
        </property>
    </bean>
</beans>

注入第三方Bean

以druid距离

第一步:导坐标

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.16</version>
</dependency>

第二步:编写配置文件

<?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-4.0.xsd">
    
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>
</beans>

处理敏感信息

我们发现我们的账号和密码直接写到了xml配置文件中,这显然是不合理的
一般我们是写道properties配置文件中。

第一步:开启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
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
第二步:使用context命名空间,加载指定properties文件
<context:property-placeholder location="classpath:*.properties"/>
第三步:使用${}读取加载的属性值
<property name="username" value="${jdbc.username}"/>

小结

获取容器方式

方式一:类路径加载配置文件

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

方式二:文件路径加载配置文件

ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\applicationContext.xml");

方式三:加载多个配置文件

ApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml","bean2.xml");

获取bean的方式

1.使用bean名称获取

BookDao bookDao = (BookDao)ctx.getBean("bookDao");

2.使用bean名称获取并指定类型

BookDao bookDao = ctx.getBean("bookDao",BookDao.class);

3.使用bean类型获取

BookDao bookDao = ctx.getBean(BookDao.class);

bean相关

<bean
	id="bookDao"								bean的id
	name="dao bookDaoImpl daoImpl"			    bean的别名
	class="com.Angelday.dao.impl.BookDaoImpl"	bean类型,静态工厂类,FactoryBean类
	scope="singleton"							控制bean的实例数量
	init-method="init"							生命周期初始化方法
	destroy-method="destory"					生命周期销毁方法
	autowire="byType"							自动装配类型
	factory-method="getInstance"				bean工厂方法,应用于静态工厂或实例工厂
	factory-bean="com.itheima.factory.BookDaoFactory"实例工厂
	lazy-init="true"							控制bean延迟加载
/>

纯注解开发

引入

前面我们在声明一个被Spring容器管理的Bean时,需要在XML中声明

<bean id="userDao" class="com.angelday.dao.UserDao">

而我们使用注解开发时,只需要想要声明Bean的类中添加一个注解@Component()并且在括号里添加这个Bean的id

@Component("id")
public class UserDao{
	public void save(){
		System.out.println("userDao-->run!");
	}
}

这样我们只能够声明这是一个被管理的bean,但是Spring容器并不能直接识别到它,所以我们需要创建一个类,来告诉Spring要去哪里找bean我们在根目录下创建一个新的包:config,用来存放配置类

//这个注解用来声明这是一个Spring的配置类
@Configuration
//这个注解用来告诉Spring需要去哪里扫描bean
@ComponentScan("com.angelday")
public class SpringConfig{
}

注:如果还要使用配置文件,我们要添加< context:component-scan base-package="com.angelday"/>

创建好这个配置类后,我们就可以删除xml配置文件了。
此时我们在获取容器时,也不再加载配置文件,而是加载配置类

public class App{
	public static void main(){
		//获取IoC容器,并且传入配置类
		ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
		//获取Bean,使用getBean("id");方法
		UserDao userDao = (UserDao)ctx.getBean("userDao");
		userDao.save();
	}
}

与配置文件对比

注解只是代替了以前的内容

  • 原先xml配置文件SpringConfig类代替
  • xml格式写为类中的@Configuration注解
  • < bean>标签被@Component代替
  • id属性写在@Component("id")
  • class属性写到配置类的@ComponentScan("com.angelday")
  • 获取IoC容器的对象ClassPatjXmlApplicationContext换为AnnotationConfigApplicationContext

注意:Spring提供了@Component注解的三个衍生注解

注解说明
@Controller表现层bean定义
@Service业务层bean定义
@Repository数据层bean定义

自动装配

只需要在需要装配的属性前加上@Autowired
并且可以省略配置文件式开发使用的Setter方法

public class BookService{
	
    @Autowired
	private BookDao bookDao;

    public void save(){
        bookDao.save();
    }
}

按类型自动装配:@Autowired
按名称自动装配:@Qualifier(“bean’s id”)

注意:@Qualifier必须配合@Autowired注解使用

注入简单类型
在属性上直接使用@Value()注解

@Repository("userDao")
public class UserDao{
	@Value("Zhangsan")
	private String name;
}

注入外部Properties

name=zhangsan

在Spring配置类中添加@PropertySource()注解

@Configuration
@ComponentScan("com.angelday")
@PropertySource("classpath:Xxx.properties")
public class SpringConfig{
}

在需要注入的属性前添加@Value()注解

@Repository("userDao")
public class UserDao{
	@Value(#{name})
	private String name;
}

注入第三方bean

此处还是以druid距离

  1. 添加一个配置类用来获取要管理的对象
    此处以添加Druid的数据源为例
public class JdbcConfig{
	//定义一个方法获取管理的对象
    //@Bean表示当前方法返回值是一个bean
	@Bean
	public DataSource dataSource(){
		DruidDataSource dds = new DruidDataSource();
		ds.setDriverClassName("com.mysql.jdbc.Driver");
		ds.setUrl("jdbc:mysql://localhost:3306/db_name");
		ds.setUsername("root");
		ds.setPassword("123456");

		return dds;
	}
}
  1. 在SpringConfig配置类中导入这个配置类
    使用@Import引入
@Configuration
@Improt(JdbcConfig.class)
public class SpringConfig{
}
  1. 处理敏感信息
    上面简单类型数据不应该写在类里,所以可以使用@Value的方式注入简单数据类型
public class JdbcConfig{
	@Value("com.mysql.jdbc.Driver")
	private String driver;
	@Value("jdbc:mysql://localhost:3306/db_name")
	private String url;
	@Value("root")
	private String userName;
	@Value("123456")
	private String password;

	@Bean
	public DataSource dataSource(){
		DruidDataSource dds = new DruidDataSource();
		ds.setDriverClassName(driver);
		ds.setUrl(url);
		ds.setUsername(userName);
		ds.setPassword(password);
		return dds;
	}
}

对于引用数据类型,可以直接在方法的形参处添加

public class JdbcConfig{
    //假设这个Bean需要依赖与BookDao
	@Bean
    //直接作为形参传入即可,Spring会自动装配
	public DataSource dataSource(BookDao bookDao){
        System.out.println(bookDao);
		DruidDataSource dds = new DruidDataSource();
		return dds;
	}
}
  • 引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象

AOP

AOP(Aspect Oriented Programming)面向切面编程,一种编程范式,指导开发者如何组织程序结构
OOP(object oriented Programming)面向对象编程

作用︰在不惊动原始设计的基础上为其进行功能增强

Spring理念∶无入侵式/无侵入式

核心概念

  • 连接点 (JoinPoint):
    • 程序执行过程中的任意位置,粒度非常细,可以是执行方法、抛出异常、设置变量等具体的操作点。
    • 在 Spring AOP 中,通常理解为方法的执行,因为方法的调用是常见的可被 AOP 切入的连接点。例如,当一个对象的某个方法被调用时,这个方法的执行点就是一个连接点。
  • 切入点 (Pointcut):
    • 是用来匹配连接点的表达式或规则。
    • 在 Spring AOP 中,一个切入点可以有不同的粒度和范围。
      • 可以只描述一个具体方法,比如 “com.angelday.dao 包下的 BookDao 接口中的无形参无返回值的 save 方法”,这是非常具体的切入点定义,只有当这个特定的方法被执行时,AOP 才会介入。
      • 也可以匹配多个方法,例如 “所有的 save 方法”,这会匹配项目中任何类中的名为 save 的方法;“所有的 get 开头的方法”,只要方法名以 get 开头就会被匹配;“所有以 Dao 结尾的接口中的任意方法”,只要接口名称以 Dao 结尾,其中的任何方法执行都会被视为切入点;“所有带有一个参数的方法”,无论在哪个类中,只要方法有一个参数就符合这个切入点的定义。
  • 通知 (Advice):
    • 是在切入点处执行的操作,也就是所谓的共性功能。
    • 在 Spring AOP 中,功能最终以方法的形式呈现。常见的通知类型有前置通知(Before Advice)、后置通知(After Advice)、环绕通知(Around Advice)等。
      • 前置通知在目标方法执行之前执行,可以用于一些准备工作,如参数验证、日志记录等。
      • 后置通知在目标方法执行之后执行,可以用于处理方法的返回结果、记录方法执行时间等。
      • 环绕通知可以完全控制目标方法的执行,包括在目标方法执行前后执行额外的代码,甚至可以决定是否执行目标方法。
  • 通知类:
    • 定义通知的类,通常包含一个或多个通知方法。这些方法会在特定的切入点被触发执行,实现 AOP 的横切关注点分离。
    • 通知类可以通过注解或在 XML 配置文件中进行定义,以便被 Spring AOP 框架识别和管理。
  • 切面 (Aspect):
    • 描述通知与切入点的对应关系。一个切面是一个模块化的横切关注点的实现,它将特定的通知应用到一组匹配的切入点上。
    • 例如,定义一个日志记录的切面,可以将前置通知(记录方法开始执行的日志)和后置通知(记录方法执行结束的日志)应用到多个切入点,如特定包下的所有业务方法。
    • 在 Spring 中,可以通过注解或 XML 配置来定义切面,使得 AOP 功能更加易于管理和维护。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值