1. Spring IoC
IOC: Inversion of Control 控制反转
反转的概念:
- 正转:程序主动去创建对象
- 反转:IOC容器来创建对象
控制的概念:
控制了外部资源获取[对象、文件等]
传统应用程序都是由类内部主动创建对象,导致类与类之间高耦合,难于测试,有了IOC容器后,把创建和查找依赖对象的控制器交给了容器,由容器进行注入,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合.
理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”
谁依赖谁:应用程序依赖于IOC容器
为什么需要依赖:应用程序需要IOC容器来提供对象需要的外部资源
谁注入谁:很明显IOC容器注入应用程序某个对象,应用程序依赖的对象
注入了什么:注入的是某个对象所需要的外部资源[对象、资源、常量数据]
实现IOC的几种方式
- 1.xml
- xml中通过bean标签配置要注入的类
- 在程序中通过ApplicationContext加载该xml文件
- 使用getBean拿到容器中的bean
- 2.annotation
- 在要注入容器的类上使用@Component、@Service、@Controller注解
- 在xml中通过context:component-scan开启包扫描
- 在程序中通过ApplicationContext加载该xml文件
- 使用getBean拿到容器中的bean
- 3.自动装配
- 使用@Autowired,@Inject,@Resource,@Qualifier注入bean
- 4.零配置实现 通过@Configuration注解的类来替代xml进行配置
- 使用@Configuration注解的类替代xml文件对要注入的bean进行配置
2. Spring注解总结
1.@Component、@Repository,@Service、@Controller注解
它可以被Spring容器识别,启动Spring后,会自动把它转成容器管理的Bean。
- @Component:泛指组件,当组件不好归类的时候,我们可以使用这个注解进行注解。
- @Repository:用于对DAO实现类进行注解。
- @Service: 用于对业务层注解,但是目前该功能与 @Component 相同。
- @Controller:用于对控制层注解,但是目前该功能与 @Component 相同。
2.@Autowired,@Resource,@Qualifier,@Inject注解
可以对成员变量、方法和构造函数进行注解,来完成自动装配的工作
- @Autowired:默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合@Qualifier一起使用
- @Qualifier:在@Autowired的基础上根据名称进行装配
- @Resource:默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入
- @Inject:@Autowired
注意:
1.@Resouce注解是J2EE提供,@Autowired是Spring提供
2.@Resource和@Autowired都可以书写注解在字段或者该字段的setter方法之上
3.@Autowired可以对成员变量、方法以及构造函数进行注释,而@Qualifier的注解对象是成员变量、方法入参、构造函数入参
4.@Qualifier(“XXX”) 中的 XX是 Bean 的名称,所以 @Autowired 和 @Qualifier 结合使用时,自动注入的策略就从 byType 转变成 byName 了
5.@Autowired 注释进行自动注入时,Spring 容器中匹配的候选 Bean 数目必须有且仅有一个,通过属性required可以设置非必要
6.@Resource装配顺序
如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
3. Spring AOP
面向切面编程 通过预编译和运行期动态代理实现程序功能的横向统一的技术 可以对业务逻辑的各个部分进行隔离 降低耦合性 分为动态织入和静态织入
- 静态织入:在编译前需织入内容 成本很高
- 动态织入:无需改变目标模块
原理:通过Advice定义横切逻辑
Spring支持五种类型的Advice
- 1) 前置通知: MethodBeforeAdvice
- 2) 后置通知: AfrerReturningAdvice
- 3) 环绕通知:MethodInterceptor
- 4) 异常抛出通知:ThrowsAdvice
- 5) 引介通知: IntroductionInterceptor 类中添加新的方法属性
实现方法:
1.通过Spring实现AOP
自定义Advice类
使用ProxyFactory拿到工厂类
调用setTarget设置要代理的类
调用addAdvice添加通知
最后调用getProxy()拿到代理类
2.通过IOC配置实现AOP
和上一步类似 只是将ProxyFactory注入到容器中
自定义Advice类
将Advice和要代理的类注入IOC容器
注入ProxyFactoryBean并且配置好代理类和通知
使用getBean直接获取到要代理的对象
3.使用xml配合AOP
通知无需再继承抽象类或者实现接口,只要定义一个简单的bean,可以在方法中使用JoinPoint获得连接点的信息
首先将通知类和要代理类注入Spring容器
再配置aop
<!-- 配置AOP -->
<!-- proxy-target-class属性表示被代理的类是否为一个没有实现接口的类,Spring会依据实现了接口则使用JDK内置的动态代理,如果未实现接口则使用cblib -->
<aop:config proxy-target-class="true">
<!--切面配置-->
<!--ref表示通知对象的引用-->
<aop:aspect ref="advicesImpl">
<!--配置切入点-->
<aop:pointcut id="pointcut1" expression="execution(* com.hqq.day09.proxy.Math.*(..))"/>
<!--声明通知 method指定通知类型 pointcut指定切点-->
<aop:before method="beforeMethod" pointcut-ref="pointcut1"/>
<aop:after method="afterMethod" pointcut-ref="pointcut1"/>
<aop:around method="aroundMethod" pointcut="execution(* com.hqq.day09.proxy.Math.s*(..))"/>
<aop:after-throwing method="afterThrowing" pointcut="execution(* com.hqq.day09.proxy.Math.d*(..))"
throwing="ex"/>
<aop:after-returning method="afterReturning" pointcut="execution(* com.hqq.day09.proxy.Math.m*(..))"
returning="result"/>
</aop:aspect>
</aop:config>
4.使用注解配置
使用注解注入要代理类
使用@Component、@Aspect将通知类注入Spring容器
在通知中相应的方法上使用注解
@Before("execution(* com.zhangguo.Spring052.aop02.Math.*(..))")
public void before(JoinPoint jp){
System.out.println("----------前置通知----------");
System.out.println(jp.getSignature().getName());
}
XML文件中配置aspectj
<aop:aspectj-autoproxy proxy-target-class="true"/>
5.aspectJ 切点函数
用在XML配置文件中
@AspectJ使用AspectJ专门的切点表达式描述切面
方法切点函数:通过描述目标类方法信息定义连接点。
方法参数切点函数:通过描述目标类方法入参信息定义连接点。
目标类切点函数:通过描述目标类类型信息定义连接点。
代理类切点函数:通过描述代理类信息定义连接点。
常用AspectJ表达式函数
- execution():满足匹配模式字符串的所有目标类方法的连接点
- @annotation():任何标注了指定注解的目标方法链接点
- args():目标类方法运行时参数的类型指定连接点
- @args():目标类方法参数中是否有指定特定注解的连接点
- within():匹配指定的包的所有连接点
- target():匹配指定目标类的所有方法
- @within():匹配目标对象拥有指定注解的类的所有方法
- @target():匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解
- this():匹配当前AOP代理对象类型的所有执行方法
最常用的是:execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)
6.aspectJ通知注解
7.零配置实现Spring IoC与AOP
@Configuration //用于表示当前类为容器的配置类,类似
@ComponentScan(basePackages=”com.zhangguo.Spring052.aop05”) //扫描的范围,相当于xml配置的结点
@EnableAspectJAutoProxy(proxyTargetClass=true) //自动代理,相当于<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
public class ApplicationCfg {
//在配置中声明一个bean,相当于<bean id=getUser class="com.zhangguo.Spring052.aop05.User"/>
@Bean
public User getUser(){
return new User();
}
}