Spring5
IOC
IOC 容器原理分析
https://javadoop.com/post/spring-ioc点我
bean管理
- spring中有两种类型bean,一种是普通bean,一种是工厂bean
- 普通bean就是在配置文件中定义什么类型的,getBean的时候就是什么类型
- 工厂bean是定义的什么类型,返回的不一定是配置文件中定义的类型:
- 让类实现FactoryBean接口,并实现方法,在方法中定义要返回的bean类型
public class FactoryBeanDemo implements FactoryBean { @Override public Object getObject() throws Exception { Emp emp = new Emp(); return emp; } @Override public Class<?> getObjectType() { return null; } @Override public boolean isSingleton() { return false; } }
bean的作用域
- spring中默认创建的bean是单例的,即配置文件中scope属性为singleton,在加载配置文件的时候创建对象
- scope属性设置为prototype,则创建出来的对象是多实例的,在getBean的时候才创建对象
bean的生命周期
- 通过构造器创建bean实例
- 为bean的属性赋值和引用其他的bean
- 调用bean的初始化方法(需要配置)
- 获取需要的bean对象
- 容器关闭的时候,调用bean的销毁方法(需要配置)


加上bean的后置处理器,bean的生命周期由7步
会给所有的bean对象的都加上后置处理器
- 通过构造器创建bean实例
- 为bean的属性赋值和引用其他的bean
- 把bean的实例传递给后置处理器方法
postProcessBeforeInitialization - 调用bean的初始化方法(需要配置)
- 把bean的实例传递给后置处理器方法
- 获取需要的bean对象
postProcessAfterInitialization - 容器关闭的时候,调用bean的销毁方法(需要配置)
运行结果:


XML方式自动装配(很少用到)
- 通过在bean标签里面加入autowire属性实现自动装配
- 1、byName,通过名字实现
- 2、byType,通过属性类型实现
IOC操作bean,为bean属性引入外部属性文件
- 加入
<context:property-placeholder location="classpath:"></context:property-placeholder>
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<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>
</bean>
IOC操作bean管理
-
注解:代码的特殊标记
-
使用注解可以标注在类、方法、属性上
-
使用注解的目的就是简化xml配置
-
spring针对bean管理中创建对象提供注解
- Component,标注在组件上
- Controller,通常标注在web层
- Service,通常标注在业务处理层
- Repository,通常标注在DAO层
以上四个注解作用都是一样
-
在xml配置文件中添加
<context:component-scan base-package=" "></context:component-scan> -
在对应的类上加入以上注解就可以将创建对象交由spring容器管理,注解属性value默认值是类名首字母 小写,相当于配置文件中的id属性
<!--只扫描包含 Controller注解的类--> <context:component-scan base-package="com.feng" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan><!--不扫描包含Controller的--> <context:component-scan base-package="com.feng"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> -
基于注解方式实现属性注入
- 1、@Autowire,根据类型注入
- 2、@Qualifier,根据属性名称注入,要与 Autowire配合使用
@Autowired @Qualifier(value = "userDaoImpl") private UserDao userDao;- 3、@Resource,属性名称,类型都可以
- 4、@Value,注入普通属性
完全注解开发
- 创建SpringConfig的spring配置类,在该类上加上@Configuration和@ComponentScan(basePackages = “”)
AOP
1、定义
- 利用aop可以将业务逻辑的各个部分进行分离,降低耦合性,提高可重用性,提高开发效率
- 不修改源代码,实现添加新功能
2、原理
- 有接口,使用jdk动态代理
- 添加接口实现类代理对象
- 没有接口,使用CGLIB动态代理
- 创建当前类的子类的代理对象,增强类的方法
- AOP,jdk动态代理
- 使用Proxy类里面的方法创建代理对象
- 调
newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h) - 第一个参数,类加载器
- 第二个参数,增强方法所实现的类,该类实现的接口,可以有多个接口
- 第三个参数,实现这个接口InvocationHandler,创建代理对象,写增强的部分
3、AOP术语
- 1、连接点:
类里面哪些方法可以被增强,这些方法可以称为连接点 - 2、切入点:
实际被增强的方法,称为切入点 - 3、通知(增强):
实际增强的逻辑部分称为通知或增强- 前置通知
- 后置通知
- 环绕通知
- 异常通知
- 最终通知
- 4、切面:
把通知应用到切入点的过程
4、AOP操作
- 1、spring框架一般都基于AspectJ实现AOP 操作
- aop不是spring的组成部分,一般把AspectJ和spring一起使用,进行AOP操作
- 2、基于xml实现和基于注解实现
- 3、切入点表达式
- 作用:知道对哪个类的哪个方法进行增强
- 语法结构:execution([权限修饰符] [返回值类型] [类全路径] [方法名称] (参数列表))
- 例:execution(* com.feng.dao.Book.*(…))表示对Book类下面的所有方法进行增强
- 4、引入依赖后,在代理类上面加入注解@Aspect,在xml配置文件中添加
aop:aspectj-autoproxy></aop:aspectj-autoproxy>标签开启Aspect生成代理对象 - 例:
@Component
@Aspect
public class UserProxy {
@Before(value = "execution(* com.feng.bean.User.*(..))")
public void before() {
System.out.println("前置通知Before....");
}
//异常也会执行
@After(value = "execution(* com.feng.bean.User.*(..))")
public void after() {
System.out.println("最终通知After....");
}
//有返回值之后才执行,异常不执行
@AfterReturning(value = "execution(* com.feng.bean.User.*(..))")
public void afterReturn() {
System.out.println("后置通知(返回通知)AfterReturning..");
}
//异常通知
@AfterThrowing(value = "execution(* com.feng.bean.User.*(..))")
public void afterThrowing() {
System.out.println("异常通知,afterThrowing。。。");
}
//环绕通知,在被代理类的方法前后都会执行
@Around(value = "execution(* com.feng.bean.User.*(..))")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕通知前,around....");
joinPoint.proceed();
System.out.println("环绕通知后,around。。。");
}
}
- 加入异常:

- 没有异常

- 相同的切入点抽取
利用@Pointcut(value=“切入点表达式”) - 设置增强类优先级
在增强类的方法上添加@Order注解,值为int类型,值越小优先级越高 - xml配置aop
<!--被代理的类-->
<bean class="com.feng.aopxml.Book" id="book"></bean>
<!--代理类-->
<bean class="com.feng.aopxml.BookProxy" id="bookProxy"></bean>
<aop:config>
<!--切入点-->
<aop:pointcut id="pointcut" expression="execution(* com.feng.aopxml.Book.*(..))"/>
<!--定义切面:把通知应用到切入点的过程-->
<aop:aspect ref="bookProxy">
<!-- 前置通知-->
<aop:before method="before" pointcut-ref="pointcut"></aop:before>
</aop:aspect>
</aop:config>
- 全注解方式,只需要添加spring配置类,如下:
@Configuration
@ComponentScan(value = "com.feng")
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}
注意:使用xml方式时,加载配置文件是用new ClassPathXmlApplicationContext("beans2.xml")
改为注解方式应该使用new AnnotationConfigApplicationContext(ConfigAop.class);
5、spring aop和AspectJ AOP有什么区别
- 1、springaop是运行时增强,AspectJ是编译时增强
- 2、springaop是基于代理,而AspectJ是基于字节码操作
- 3、切面多,使用AspectJ,因为比spring快很多
JDBC Template
1、概念
- spring框架对jdbc进行了封装,使用jdbc Template方便了对数据库进行操作
2、需要的引入的依赖
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--对jdbc的封装-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<!--为JDBC、Hibernate、JDO、JPA等提供的一致的声明式和编程式事务管理。-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<!--Spring 的ORM模块提供对常用的ORM框架的管理和辅助支持-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
配置数据库连接池
<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/yonghedb"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
配置JDBCTemplate,注入数据源对象
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
事务
概念
- 事务是数据库最基本的单元,逻辑上一组操作,要么都成功,要么都失败
特性
- 1、原子性:一组操作要么都成功,一个失败都失败
- 2、一致性:事务开始之前和事务结束以后,数据库的完整性约束没有被破坏
- 3、隔离性:多个事务之间相互隔离,互不干扰
- 3、永久性:该事务对数据的所有更改将永久保存在数据库,不会被回滚
实现
- 配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
- 开启事务注解
- 在xml配置上添加命名空间
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation:http://www.springframework.org/schema/tx http://www.springframework.org/schema/beans/spring-tx.xsd
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
- 在需要添加事务的类,添加注解@Transaction也可以添加在方法上
如果在类上,表示该类里面的所有的方法,添加事务
如果在方法上,表示仅该方法添加事务
声明式事务管理参数配置
- @Transaction这个注解里面可以配置相关参数
public @interface Transactional {
@AliasFor("transactionManager")
String value() default "";
@AliasFor("value")
String transactionManager() default "";
Propagation propagation() default Propagation.REQUIRED;
Isolation isolation() default Isolation.DEFAULT;
int timeout() default -1;
boolean readOnly() default false;
Class<? extends Throwable>[] rollbackFor() default {};
String[] rollbackForClassName() default {};
Class<? extends Throwable>[] noRollbackFor() default {};
String[] noRollbackForClassName() default {};
}

浙公网安备 33010602011771号