Spring

mac2026-05-04  8

Spring相关知识

初次学习Spring的笔记一、Spring解决的主要问题二、IoC(Inversion of Control,控制反转)(一)概念(二)配置方式1、基础准备2、XML-Bean式IoC配置(1)XML配置(2)resources中database.properties配置(3)使用 3、注解式IoC(1)配置包扫描路径(2)使用类加注解(3)使用时,直接读取配置文件,根据类名(单驼峰规则)来获取bean; 4、Java类配置IoC(1)新建AppConfig类,提供方法,添加注解,替代xml中bean的书写;(2)使用时读取AppConfig类,根据类名(单驼峰规则)来获取bean; 5、扫描方式IoC配置(1)新建AppConfig类,添加注解设置扫描包路径;(2)bean对应类添加注解;(3)使用时读取AppConfig类,根据类名(单驼峰规则)来获取bean; (三)实例化方法1、默认构造器实例化2、静态工厂方法实例化3、工厂bean实例化4、Spring的FactoryBean接口实例化 (四)依赖注入方式1、setter注入2、构造器注入 (五)bean生命周期及其作用域1、作用域2、生命周期(1)方式一(2)方式二 (六)IoC的优势 三、AOP(Aspect Oriented Programming,面向切面编程)(一)概念(二)应用场景(三)配置方式1、准备工作2、xml配置-前置、后置、异常通知式(1)创建事务类,提供开启事务、提交事务和回滚事务方法;(2)配置xml文件;(3)调用目标对象; 3、xml配置-环绕异常式(1)创建事务类,提供一个方法,用于开启事务、提交事务和回滚事务;(2)配置xml文件(3)调用目标对象 4、扫描式(1)编写xml文件,提供扫描包的路径,设置aspectj自动代理;(2)目标对象类添加注解,并写入自定义的id,spring将根据此来识别bean;(3)创建事务切面类,配置切入点、环绕通知;(4)调用目标对象 5、Java类扫描式(1)创建AppConfig类,设置扫描路径,设置aspectj自动代理;(2)目标对象类添加注解(3)创建事务切面类,配置切入点、环绕通知(4)调用目标对象

初次学习Spring的笔记

一、Spring解决的主要问题

“框架”是对开发领域中的经验者,将对于该领域事务的最佳实现总结编写而成最佳流程。使用者只需要遵守它的开发规则,就可以实现良好的模块化,避免软件开发中潜在的问题,并且更加高效、更加健壮地编写自己的代码。 而Spring就是一个成熟的框架,开发人员框架中填充自己的业务逻辑就能完成一个模块划分清晰纷的系统。

二、IoC(Inversion of Control,控制反转)

(一)概念

常规思维下,某个类需要初始化它的私有化属性就必须进行主动搜索需要的外部资源,但在使用容器的情况下,控制权便从调用的类转换到spring容器,由spring来实例化对象和依赖注入,这样反转资源获取方向的思想被称为控制反转。

(二)配置方式

1、基础准备

在使用Spring提供的功能之前,首先要导入spring的依赖,即在pom.xml文件中添加dependency;

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

为了方便理解各种配置方式的实现,我们创建一个实验项目: 此时,实验项目的目录结构为: 简单实现登录功能,APP为程序启动点,调用MainUI的方法显示菜单选项,再根据用户选择调用AccountManager的方法进行登录或者注册,然后通过Service层和DAO层的处理访问数据库,核对用户名和密码或者添加用户; 在该项目基础上,我们实现各种IoC的配置方式。

2、XML-Bean式IoC配置

(1)XML配置

在resources文件夹内创建一个Spring Config文件:选中resources文件夹,右键 -> New -> XML Configuration File -> Spring Config,命名为applicationConfig,在该文件中,为该项目各个类配置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.xsd"> <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"> <property name="location" value="database.properties"></property> </bean> <bean name="datasource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClass}"></property> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner"> <constructor-arg name="ds" ref="datasource"></constructor-arg> </bean> <bean id="mainUI" class="com.woniuxy.springlogin.UI.MainUI"> <constructor-arg name="accountManager" ref="accountManager" ></constructor-arg> </bean> <bean id="accountManager" class="com.woniuxy.springlogin.menu.AccountManager"> <constructor-arg index="0" ref="userService"></constructor-arg> </bean> <bean id="userDao" class="com.woniuxy.springlogin.dao.impl.UserDAOImpl"> <constructor-arg index="0" ref="queryRunner"></constructor-arg> </bean> <bean id="userService" class="com.woniuxy.springlogin.service.impl.UserServiceImpl"> <constructor-arg index="0" ref="userDao"></constructor-arg> </bean> </beans>
(2)resources中database.properties配置
jdbc.url=jdbc:mysql://localhost:3306/bill?useUnicode=true&characterEncoding=utf8 jdbc.username=root jdbc.password=78963 jdbc.driverClass=com.mysql.jdbc.Driver

属性名前缀jdbc是为了避免与系统变量的冲突;

(3)使用
public class App { public static void main( String[] args ) { ApplicationContext ac= new ClassPathXmlApplicationContext("applicationContext.xml"); MainUI mainUI = ac.getBean("mainUI", MainUI.class); mainUI.start(); } }

3、注解式IoC

(1)配置包扫描路径

在resources目录下,编写applicationContext.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" 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 https://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.woniuxy.springtest"/> </beans>
(2)使用类加注解

1、注册SpringBean(代码层面没有区别,业务处理层有区别):@Controller(controller,控制器),@Service(服务),@Repository(DAO),@Component(其他组件); 2、自动依赖注入:@Autowired,@value; 例如,MainUI 添加注解注册bean,并自动依赖注入;

@Controller public class MainUI { @Autowired private AccountManager accountManager; //方法 }

其余类,依此处理;

(3)使用时,直接读取配置文件,根据类名(单驼峰规则)来获取bean;
public class App { public static void main( String[] args ) { ApplicationContext ac= new ClassPathXmlApplicationContext("applicationContext.xml"); MainUI mainUI = ac.getBean("mainUI", MainUI.class); mainUI.start(); } }

4、Java类配置IoC

(1)新建AppConfig类,提供方法,添加注解,替代xml中bean的书写;

注解 (1)@Configuration:标记一个类为配置类; (2)@Bean:标记某个方法返回值为spring的bean; (3)initMethod / destroyMethod / scope;

@Configuration public class AppConfig { /* * 创建一个叫做mainUI的bean * 方法名就是bean的id/name * 类型就是返回值类型 * */ @Bean public MainUI mainUI(){ MainUI mainUI = new MainUI(); mainUI.setAccountManager(accountManager()); return mainUI; } @Bean public AccountManager accountManager(){ return new AccountManager();; } }
(2)使用时读取AppConfig类,根据类名(单驼峰规则)来获取bean;
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class); MainUI mainUI = annotationConfigApplicationContext.getBean("mainUI", MainUI.class); mainUI.start();

5、扫描方式IoC配置

(1)新建AppConfig类,添加注解设置扫描包路径;
@Configuration @PropertySource("database.properties") @ComponentScan("com.woniuxy.springtest") public class AppConfig { }
(2)bean对应类添加注解;
@Controller public class MainUI { @Autowired private AccountManager accountManager; \\方法 }
(3)使用时读取AppConfig类,根据类名(单驼峰规则)来获取bean;
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class); MainUI mainUI = annotationConfigApplicationContext.getBean("mainUI", MainUI.class); mainUI.start();

(三)实例化方法

1、默认构造器实例化

通过构造器,创建属性的实例。例如,在MainUI类中,需要创建AccountManager类的实例才能调用其方法,于是将AccountManager类的实例设置为MainUI类的私有属性,并自定义构造方法;

private AccountManager accountManager; public MainUI(AccountManager accountManager) { this.accountManager = accountManager; }

然后xml文件中为Mainui配置bean,如下:

<bean id="mainUI" class="com.woniuxy.springlogin.UI.MainUI"> <constructor-arg index="0" ref="accountManager" ></constructor-arg> </bean>

或者

<bean id="mainUI" class="com.woniuxy.springlogin.UI.MainUI"> <constructor-arg name="accountManager" ref="accountManager" ></constructor-arg> </bean>

id唯一标记一个bean,class指向该bean的类,index表示MainUI类构造函数的第几个参数(从0开始),name可通过值匹配构造函数参数名,ref指向另一个bean;

2、静态工厂方法实例化

即调用某个类的静态方法,该方法返回一个实例。例如,调用JDBCUtils类的getConnection方法,获得一个connection,此时配置bean的方式为:

<bean id="connection" class="Util.JDBCUtils" factory-method="getConnection"></bean>

id唯一标记一个bean,class指向类,factory-method指向该类的静态方法;

3、工厂bean实例化

通过自定义工厂类,提供方法创建目标类的实例。例如,HolidayFactory类提供普通成员方法create创建并返回一个Holiday实例,此时,配置bean的方式为:

<bean id="holidayFactory" class="Entity.HolidayFactory"></bean> <bean id="holiday" factory-bean="holidayFactory" factory-method="create"></bean>

factory-bean指向构造该bean实例的另一个bean,factory-method指定构造实例的方法;

4、Spring的FactoryBean接口实例化

通过新建工厂类实现FactoryBean接口,实现其方法创建目标类的实例。例如,新建类CarFactory,实现FactoryBean<Car>接口,泛型指定需要构建实例的类,实现getObject()方法,返回一个Car对象,实现getObjectType()方法,返回Car.class,此时配置bean的方式为:

<bean id="car" class="Entity.CarFactory" ></bean>

此实例化方法只需要配置一个bean,该bean创建的实例为工厂类的getObject()方法的返回值,只需要设置class指向工厂类即可;

(四)依赖注入方式

1、setter注入

即通过为该类的成员变量提供setter方法,xml文件中配置bean,从而得到成员变量实例。例如,新建类Person :

public class Person { private int age; private List<String> hobbies; private Set<Integer> numbers; public void setAge(int age) { this.age = age; } public void setHobbies(List<String> hobbies) { this.hobbies = hobbies; } public void setNumbers(Set<Integer> numbers) { this.numbers = numbers; } }

配置bean:

<bean id="person" class="Entity.Person"> <property name="age" value="10"></property> <property name="hobbies"> <list> <value>游泳</value> <value>打游戏</value> </list> </property> <property name="numbers"> <set> <value>1</value> <value>2</value> <value>3</value> </set> </property> </bean>

value:注入基本类型; ref:注入已有的bean; list、map、set:注入相应类型,这些类型也可再通过ref标签注入已有的bean;

2、构造器注入

通过构造器参数,实现依赖注入。例如,在MainUI类中,需要创建AccountManager类的实例才能调用其方法,于是将AccountManager类的实例设置为MainUI类的私有属性,并自定义构造方法;

private AccountManager accountManager; public MainUI(AccountManager accountManager) { this.accountManager = accountManager; }

然后xml文件中为MainUI配置bean,如下:

<bean id="mainUI" class="com.woniuxy.springlogin.UI.MainUI"> <constructor-arg index="0" ref="accountManager" ></constructor-arg> </bean>

或者

<bean id="mainUI" class="com.woniuxy.springlogin.UI.MainUI"> <constructor-arg name="accountManager" ref="accountManager" ></constructor-arg> </bean>

id唯一标记一个bean,class指向该bean的类,index表示MainUI类构造函数的第几个参数(从0开始),name可通过值匹配构造函数参数名,ref指向另一个bean;

(五)bean生命周期及其作用域

1、作用域

bean的作用域有五种,通过scope属性来指定,默认使用单例; ①prototype(原型) => 每次创建一个实例; ②singleton(单例) => 一个bean的定义,只有一个实例,不是一个类只有一个实例; ③request:一个请求一个实例; ④session:一个会话一个实例; ⑤websocket:一次websocket链接一个实例;

2、生命周期

bean在读取该配置文件时调用init-method创建或spring创建,销毁则在spring容器关闭时,调用destroy-method销毁,有两种方式设置init-method和destroy-method;

(1)方式一

bean标签添加属性init-method和destroy-method,指向类中相应方法。例如,创建类Pig,其中start()方法为创建,end()方法为销毁,此时bean的配置为;

<bean id="pig" class="Entity.Pig" init-method="start" destroy-method="end"></bean>
(2)方式二

指向类实现InitializingBean,DisposableBean接口,实现afterPropertiesSet()和destroy()方法。此时bean的配置为bean的基本配置:

<bean id="dog" class="Entity.Dog"></bean>

(六)IoC的优势

一是解耦,即类与类之间的耦合度降低; 二是提升代码的灵活性,可维护性;

三、AOP(Aspect Oriented Programming,面向切面编程)

(一)概念

1、连接点(JoinPoint):需要加入功能的位置(通常为方法); 2、切入点(PointCut):真正执行加入功能的位置(属于连接点); 3、通知(Advice):需要实现的功能; 4、切面(Aspect):Java语言中,将切入点和通知等组装在一起的代码单元; 5、目标对象(Target):要操作的对象; 6、织入(Weave):将功能加入到切入点中的过程;

(二)应用场景

Authentication 权限 Caching 缓存 Context passing 内容传递 Error handling 错误处理 Lazy loading 懒加载 Debugging  调试 logging, tracing, profiling and monitoring 记录跟踪 优化 校准 Performance optimization 性能优化 Persistence  持久化 Resource pooling 资源池 Synchronization 同步 Transactions 事务

(三)配置方式

1、准备工作

首先添加依赖:

<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.4</version> </dependency>

2、xml配置-前置、后置、异常通知式

(1)创建事务类,提供开启事务、提交事务和回滚事务方法;
public class TransactionAdvice { public void begin(JoinPoint joinpoint){ System.out.println("开启事务"); } public void commit(JoinPoint joinpoint){ System.out.println("提交事务"); } public void rollback(JoinPoint joinpoint){ System.out.println("回滚事务"); } }
(2)配置xml文件;
<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="userService" class="com.woniuxy.aopdemo.service.impl.UserServiceImpl"></bean> <bean id="productService" class="com.woniuxy.aopdemo.service.impl.ProductServiceImpl"></bean> <!-- 通知 --> <bean id="beforeExecution" class="com.woniuxy.aopdemo.component.BeforeExecution"></bean> <bean id="afterReturnAdvice" class="com.woniuxy.aopdemo.component.PrintReturnAdvice"></bean> <bean id="performanceMonitorAdvice" class="com.woniuxy.aopdemo.component.PerformanceMonitorAdvice"></bean> <!-- 切入点 --> <bean id="pointCut" class="org.springframework.aop.support.JdkRegexpMethodPointcut"> <property name="pattern" value="com.woniuxy.aopdemo.service.impl.*Impl.*"></property> </bean> <!-- 切面配置 --> <bean id="aspect" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <!-- 切入点--> <property name="pointcut" ref="pointCut"></property> <!-- 通知--> <property name="advice" ref="performanceMonitorAdvice"></property> </bean> <!--包装目标对象--> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"> </bean> </beans>
(3)调用目标对象;
ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("aop.xml"); UserService userService = classPathXmlApplicationContext.getBean("userService", UserService.class); userService.addUser(new User()); ProductService productService = classPathXmlApplicationContext.getBean("productService", ProductService.class); productService.addProduct();

3、xml配置-环绕异常式

(1)创建事务类,提供一个方法,用于开启事务、提交事务和回滚事务;
public class TransactionArroundAdvice { public Object invoke(ProceedingJoinPoint proceedingJoinPoint){ Object result = null; try { System.out.println("开启事务"); Object[] args = proceedingJoinPoint.getArgs(); result = proceedingJoinPoint.proceed(args); System.out.println("事务提交"); } catch (Throwable throwable) { throwable.printStackTrace(); System.out.println("事务回滚"); } return null; } }
(2)配置xml文件
<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="userService" class="com.woniuxy.aopdemo.service.impl.UserServiceImpl"></bean> <bean id="productService" class="com.woniuxy.aopdemo.service.impl.ProductServiceImpl"></bean> <!-- 通知--> <bean id="txAdvice" class="com.woniuxy.aopdemo.component.TransactionArroundAdvice"/> <!-- 切面--> <aop:config> <aop:aspect ref="txAdvice"> <aop:pointcut id="servicePointcut" expression="execution(* com.woniuxy.aopdemo.service.impl.*.*(..))"/> <aop:around method="invoke" pointcut-ref="servicePointcut"/> </aop:aspect> </aop:config> <!--包装目标对象--> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"> </bean> </beans>
(3)调用目标对象
ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("aop.xml"); UserService userService = classPathXmlApplicationContext.getBean("userService", UserService.class); userService.addUser(new User()); ProductService productService = classPathXmlApplicationContext.getBean("productService", ProductService.class); productService.addProduct();

4、扫描式

(1)编写xml文件,提供扫描包的路径,设置aspectj自动代理;
<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" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!--扫描包路径--> <context:component-scan base-package="com.woniuxy.aopdemo"/> <!--设置aspectj自动代理--> <aop:aspectj-autoproxy /> </beans>
(2)目标对象类添加注解,并写入自定义的id,spring将根据此来识别bean;
@Service("userService") public class UserServiceImpl implements UserService { @Override public void addUser(User user){ System.out.println("添加用户"); for (int i = 0; i < 10000 ; i++) { System.out.print(user); } System.out.println(""); } }
(3)创建事务切面类,配置切入点、环绕通知;
@Component @Aspect public class TxAspect { @Pointcut("execution(* com.woniuxy.aopdemo.service.impl.*.*(..))") public void servicePointcut(){} @Around("servicePointcut()") public Object invoke(ProceedingJoinPoint pjp){ Object[] args = pjp.getArgs(); Object result = null; try { System.out.println("开启事务"); result = pjp.proceed(args); System.out.println("提交事务"); } catch (Throwable throwable) { throwable.printStackTrace(); System.out.println("回滚事务"); } return result; } }
(4)调用目标对象
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("aop-anno.xml"); UserService userServiceImpl = classPathXmlApplicationContext.getBean("userService", UserService.class); userServiceImpl.addUser(new User());

5、Java类扫描式

(1)创建AppConfig类,设置扫描路径,设置aspectj自动代理;
@Configuration @ComponentScan("com.woniuxy.aopdemo") @EnableAspectJAutoProxy public class AppConfig { }
(2)目标对象类添加注解
@Service("userService") public class UserServiceImpl implements UserService { @Override public void addUser(User user){ System.out.println("添加用户"); for (int i = 0; i < 10000 ; i++) { System.out.print(user); } System.out.println(""); } }
(3)创建事务切面类,配置切入点、环绕通知
@Component @Aspect public class TxAspect { @Pointcut("execution(* com.woniuxy.aopdemo.service.impl.*.*(..))") public void servicePointcut(){} @Around("servicePointcut()") public Object invoke(ProceedingJoinPoint pjp){ Object[] args = pjp.getArgs(); Object result = null; try { System.out.println("开启事务"); result = pjp.proceed(args); System.out.println("提交事务"); } catch (Throwable throwable) { throwable.printStackTrace(); System.out.println("回滚事务"); } return result; } }
(4)调用目标对象
AnnotationConfigApplicationContext acac = new AnnotationConfigApplicationContext(AppConfig.class); UserService userService = acac.getBean("userService", UserService.class); userService.addUser(new User()); ProductService productService = acac.getBean("productService", ProductService.class); productService.addProduct();
最新回复(0)