1. 概述
-
两大内核:
- IoC(Inverse Of Control):反转控制
- AOP(Aspect Oriented Programming):面向切面编程
-
优势:
- 方便解耦,简化开发
- AOP编程的支持
- 声明式事务的支持
- 方便程序的测试
- 方便集成各种优秀的框架
- 降低JavaEE API的使用难度
- 源码是经典学习案例
-
体系结构:
Core Container:Spring的核心容器组件, 包含了Spring框架最基本的支撑.
- Beans, 对应spring-beans.jar. Spring进行对象管理时依赖的jar包.
- Core, 对应spring-core.jar, Spring核心jar包.
- Context, 对应spring-context.jar, Spring容器上下文对象.
- SpEL, 对应spring-expression.jar, Spring表达式语言.
耦合及解耦
程序的耦合即为程序之间的依赖关系,包括类之间的依赖和方法之间的依赖关系。其存在降低了程序的独立性
解耦:降低程序间的依赖关系,但是并不可能做到无依赖关系。而我们要做到的程度时编译期无依赖关系,运行期间存在依赖(也就是说编译期对象类文件不存在不会产生错误,但在运行期会报错)。
- 工厂模式:属于创建型模式,为对象的创建提供了一种最佳方式。
2. IoC:
- 控制反转:将创建对象的控制权交给工厂。包括依赖注入和依赖查找
- 作用:降低程序的耦合程度(解除代码中的类之间的依赖关系)
解耦的思路:- 通过反射来创建对象而尽量避免使用new
- 通过配置文件来获取要创建的全限定类名
- 步骤:
- 获取核心容器对象
- 根据id获取类对象
spring中基于xml的IOC环境搭建
- 用于创建对象
<bean>
- 用于注入数据
<property>
- 用于改变作用范围
<bean scope="">
- 和生命周期相关
<bean init-method="" destroy-method="">
ApplicationContext(开发时多使用此方法):构建核心容器时,创建对象的方法时立即加载,适合单例模式。(可设置)
BeanFactory:构建核心容器时,创建对象的方法时延迟加载,适合多例模式。属于顶层接口,功能不如ApplicationContext完善。
依赖注入
使用构造函数提供
使用set方法提供
使用注解提供
3. Spring中常用的ioc注解
用于创建对象:
@Component
作用:把当前对象放入Spring容器中
属性:value:id。默认类名首字母改小写
@Controller
:一般用于表现层
@Service
:一般用于业务层
@Repository
:一般用于持久层
以上三个注解作用与属性与@Component
一模一样,其能使我们更加明确三层开发模式-
用于注入数据
@Autowired
作用:- 自动按照类型注入。只要IoC容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功。
- 如果 容器中没有任何bean类型和要注入的匹配,则报错。
- 如果 容器中有多个bean类型和要注入的匹配,继续按照id配对类名查找 没有则报错。
@Qualifier
- 作用:按照类注入的基础上再按照名称注入。给成员变量注入时需配合
@Autowired
使用,给方法注入时可单独使用。 - 属性:value,用于指定注入bean的id。
@Resource
- 作用:直接按照bean的id注入,可独立使用
- 属性:name,指定bean的id。
上述三个注解无法注入基本类型和String类型数据,集合类型数据的注入只能通过XML来实现。
@Value
- 作用:用于注入基本类型和String类型数据。
- 属性:value,用于指定数据的值。可使用SpEL表达式
用于改变作用范围
@Scope
作用:指定bean的作用范围
属性:value,指定范围取值。singleton-单例,prototype-多例。(global-session,解决负载均衡时服务器间session共享)和生命周期相关 (了解)
单例对象和多例对象不同
@PostConstruct
:设置初始化方法
@PreDestroy
设置销毁方法
使用下述注解可实现通过配置类替换配置文件bean.xml
@Configuration
:指定当前类为一个配置类
@ComponentScan
作用:指定spring在创建容器时要扫描的包
属性:value,包
@Bean
作用:把当前方法的返回值作为bean对象存入spring的ioc容器中
属性:name,指定bean的id
@Import
作用:导入其他的配置类
属性:value,指定其他配置文件的字节码
@PropertySource
作用:指定配置文件的名称和路径
属性:value
4. AOP
- 面向切面编程:通过预编译和运行期动态代理实现程序功能的统一维护的一种技术
- 作用:将程序中重复的代码进行提取,在需要的时候,使用动态代理的技术,在不修改源码的情况下对已有方法实现增强。
5. 动态代理模式
基于接口的动态代理
基于父类的动态代理
6. 基于AOP的相关注解
配置文件:
<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 告知spring在创建容器时要扫描的包,配置所需要的标签不是在beans的约束中,
而是一个名为context命名空间的约束中 -->
<context:component-scan base-package="com.handsomexu"></context:component-scan>
<!-- 使能aop -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
@Aspect
:表示切面
通知:
前置通知:@Before
后置通知:@After Returning
异常通知:@After Throwing
最终通知:@After
环绕通知:@Around
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;
@Aspect
public class AroundExample {
@Around("com.xyz.myapp.CommonPointcuts.businessService()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
// start stopwatch
Object retVal = pjp.proceed();
// stop stopwatch
return retVal;
}
}
在注解配置模式的aop使用中,spring对通知的调用顺序可能会出现错误的bug,建议采用环绕通知来进行动态代理模式的配置