Spring是一个开源框架,为了解决企业应用开发的复杂性而创建的,但现在已经不止应用于企业应用,是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架
从大小与开销两方面而言Spring都是轻量的
通过控制反转(IoC)的技术达到松耦合的目的
提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务进行内聚性的开发
包含并管理应用对象的配置和生命周期,这个意义上是一种容器
将简单的组件配置、组合成为复杂的应用,这个意义上是框架
Spring注入是指在启动Spring容器加载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 id="injectionService" class="main.java.com.imooc.ioc.injection.service.InjectionServiceImpl">
<constructor-arg name="injectionDao" ref="injectionDao"></constructor-arg>
</bean>
<bean id="injectionDao" class="main.java.com.imooc.ioc.injection.dao.InjectionDaoImpl"></bean>
</beans>
设值注入:
<bean id="injectionService" class="main.java.com.imooc.ioc.injection.service.InjectionServiceImpl">
<property name="injectionDao" ref="injectionDao"></property>
</bean>
<bean id="injectionDao" class="main.java.com.imooc.ioc.injection.dao.InjectionDaoImpl"></bean>
Bean配置项:
Id 作用:在整个IOC容器中作为Bean的标识
Class 具体要实例化的类
Scope 范围、作用域
Constructor arguments 构造器的参数
Properties 属性
Autowiring mode 自动装配的模式
lazy-initialization mode 满加载模式
Initialization/destruction method 初始化和销毁的方法
Bean的作用域scope
singleton:单例、指一个Bean容器中只存在一份
prototype:每次请求(每次使用)创建新的实例,destroy方式不生效
request:每次http请求创建一个实例且仅在当前request内有效
session:同上、每次http请求创建,当前session内有效
global session:基于portlet的web中有效(portlet定义了global session),如果是在web中,同session
Bean的生命周期:定义、初始化、使用、销毁。
初始化: 方法一:实现org.springframework.beans.factory.InitializingBean接口
方法二:配置init_method
销毁:方法一:实现org.springframework.beans.factory.DisposableBean接口
方法二:配置destroy-method
配置全局默认初始化、销毁方法
<?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"
default-init-method="defaultInit" default-destroy-method="defaultDestroy">
<bean id="beanLifeCycle" class="main.java.com.imooc.lifecycle.BeanLifeCycle"></bean>
</beans>
Spring中提供了一些以Aware结尾的接口,实现了Aware接口的bean在被初始化之后,可以获取响应资源
通过Aware接口,可以对Spring响应资源进行操作(一定要谨慎操作)
为对Spring进行简单的扩展提供了方便的入口
Bean的自动装配(Autowiring)
No:不做任何操作
byname:根据属性名自动装配。此选项将检查容器并根据名字查找与属性完全一致的bean,并将其与属性自动装配
byType:如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配;如果存在多个该类型bean,那么抛出异常,并指出不能使用byType方式进行自动装配;如果没有找到相匹配的bean,则什么事都不发生
Constructor:与byType方式类似,不同之处在于它应用于构造器参数。如果容器中没有找到与构造器参数类型一致的bean,那么抛出异常
Resourves:
针对于资源文件的统一接口
UrlResource:URL对应的资源,根据一个URL地址即可构建
ClassPathResource:获取类路径下的资源文件
FileSystemResource:获取文件系统里面的资源
ServletContextResource:ServletContext封装的资源,用于访问ServletContext环境下的资源
InputStreamResource:针对于输入流封装的资源
ByteArrayResource:针对于字节数组封装的资源
ResourceLoader:Resourves的加载类
Bean管理的注解实现及例子
Classpath扫描与组件管理
类的自动检测与注册Bean
<context:annotation-config/>
@Component,@Repository,@Service,@Controller
@Required
@Autowired
@Qualifier
@Resource
Classpath扫描与组件管理
从Spring3.0开始,Spring JavaConfig 项目提供了很多特性,包括使用java而不是XML定义bean,比如:
@Configuration(指把这个类当做配置文件使用),@Bean,@Import,@DependsOn
@Component是一个通用注解,可用于任何bean
@Repository,@Service,@Controller是更有针对性的注解
@Repository通常用于注解DAO类,即持久层
@Service通常用于注解Service类,即服务层
@Controller通常用于Controller类,即控制层(MVC)
类的自动检测及Bean的注册
Spring可以自动检测类并注册Bean到ApplicationContext中
<context:annotation-config/>
通过在基于XML的Spring配置如下标签(请注意包含上下文命名空间)
<context:annotation-config/>仅会查找在同一个applicationcontext中的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"
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">
<context:annotation-config></context:annotation-config>
</context:component-scan>
</beans>
为了能够检测这些类并注册响应的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"
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">
<context:component-scan base-package="所需要扫描的包名"></context:component-scan>
</beans>
base-package="" 指扫描一个包下的所有类
<context:component-scan>(可以处理整个类的注解)包含<context:annotation-config>(处理方法或成员变量的注解),通常在使用前者后,不用再使用后者
AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor也会被包含进来
使用过滤器进行自定义扫描
默认情况下,类被自动发现被注册bean的条件是:使用@Component,@Repository,@Service,@Controller注解或者使用@Component的自定义注解
可以通过过滤器修改上面的行为,如:下面例子的XMl配置忽略所有的@Repository注解并用"Stub"代替
还可以使用use-default-filters="false"禁用自动发现与注册
过滤器的Type有多种类型
annotation:注解
assignable:具体某一个类的注解
aspectj:
regex:正则表达式、通配符
custom:自定义
定义Bean
扫描过程中组件被自动检测,那么Bean名称是由BeanNameGenerator生成的(@Component,@Repository,@Service,@Controller都会有个name属性用于显式设置Bean Name)
可自定义bean命名策略,实现BeanNameGeneratoe接口,并一定要包含一个无参构造器
作用域(Scope)
通常情况下自动查找的Spring组件,其scope是singleton,Spring2.5提供了一个标识scope的注解@Scope
也可以自定义scope策略,实现ScopeMetadataResolver接口并提供一个无参构造器
代理方式
可以使用scoped-proxy属性指定代理,有三个值可选:no,interfaces,targetClass
<beans>
<context:component-scan base-package="org.example" scoped-proxy="interfaces"/>
</beans>
@Required
@Required注解适用于bean属性的setter方法
这个注解仅仅表示,受影响的bean属性必须在配置时被填充,通过在bean定义或通过自动装配一个明确的属性值
@Autowired
可以将@Autowired注解为"传统"的setter方法
可用于构造器或成员变量
默认情况下,如果因找不到合适的bean将会导致autowiring失败抛出异常,可以通过下面的方式避免
@Autowired(required=false)
将required设置为false,即不是必要的,所以就能避免异常
每个类只能有一个构造器被标记为required=true
@Autowired的必要属性,建议使用@Required注解
可以使用@Autowired注解那些众所周知的解析依懒性接口,比如:BeanFactory,ApplicationContext,Environment,ResourceLoader,ApplicationEventPublisher,and MessageSource
可以通过添加注解给需要该类型的数组的字段或方法,以提供ApplicationContext中的所有特定类型的bean
@Autowired
private List<BeanInterface> list;
可以用于装配key为String的Map
@Autowired
private Map<String, BeanInterface> map; //String 是bean的id,BeanInterface是bean的实例
如果希望数组有序,可以让bean实现org.springframework.core.Ordered接口或使用@Order注解
@Autowired是由Spring BeanPostProcessor处理的,所以不能在自己的BeanPostProcessor或BeanFactoryPostProcessor类型应用这些注解,这些类型必须通过XML或者Spring的@Bean注解加载
@Qualifier
按类型自动装配可能多个bean实例的情况,可以使用Spring的@Qualifier注解缩小范围(或指定唯一),也可以用于指定单独的构造器参数或方法参数
可用于注解集合类型变量
在XML配置文件中使用Qualifier的方式
如果通过名字进行注解注入,主要使用的不是@Autowired(即使在技术上能够通过@Qualifier指定bean的名字),替代方式是使用JSR-250@Resource注解,它是通过其独特的名称来定义来识别特定的目标(这是一个与所声明的类型是无关的匹配过程)
因语义差异,集合或Map类型的bean无法通过@Autowired来注入,因为没有类型匹配到这样的bean,为这些bean使用@Resource注解,通过唯一名称引用集合或Map的bean
@Autowired适用于fields(字段),constructors(构造器),muti-argument methods(多参数方法)这些允许在参数级别使用@Qualifier注解缩小范围的情况
@Resource适用于成员变量、只有一个参数的setter方法,所以在目标是构造器或一个多参数方法时,最好的方式是使用qualifier
基于java的容器注解
@Bean标识一个用于配置和初始化一个由SpringIoC容器管理的新对象的方法,类似于XML配置文件的<bean/>
可以再Spring的@Component注解的类中使用@Bean注解任何方法(仅仅是可以)
上一点中,通常使用的是@Configuration
@Configuration
public class AppConfig{
@Bean
public MyService myService(){
return new MyServiceImpl();
}
}
功能上等于:
<beans>
<bean id="myService" class="com.XXX.XXX.MyServiceImpl">
</beans>
@Configuration
public class AppConfig{
@Bean(service) //自定义bean name
public MyService myService(){
return new MyServiceImpl();
}
}
同时也支持init-method 和 destory-method
使用@ImportResource和Value注解进行资源文件读取
在xml配置文件中使用的方式:
用注解的方式:
@Value("${url}")
private String url;
//@Value("${username}")//这样写的话,默认取到的值是该计算机操作数据的名称xujulong
@Value("${jdbc.username}")
private String username;
@Value("${password}")
private String password;
@Resource
Spring还支持使用JSR-250@Resource注解的变量或setter方法
@Resource有一个name属性,并且默认Spring解释该值作为被注入bean的名称
如果没有显示地指定@Resource的name默认的名称是从属性名或者setter方法得出
注解提供的名字呗解析为一个bean的名称,这是由ApplicationContext的中的CommonAnnotationBeanPostProcessor发现并处理的
@PostConstruct and @PreDestroy
CommonAnnotationBeanPostProcessor不仅能识别JSR-250中的生命周期注解@Resource,在Spring2.5中引入支持初始化回调和销毁回调,前提是CommonAnnotationBeanPostProcessor是Spring的ApplicationContext中注册的
@Inject
@Inject等效于@Autowired,可以使用与类,属性,方法,构造器
@Named
如果想使用特定名称进行依赖注入(当同一种类型的bean在Ioc容器中有多个的时候,想使用特定的那一个bean),使用@Named
@Named与@Component是等效的
AOP:Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能维护的一种技术
主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等
预编译:AspectJ
运行期动态代理(JDK动态代理、CGLib动态代理):SpringAOP、JbossAOP
AOP几个相关概念
Aspect(切面):一个关注点的模块化,这个关注点可能会横切多个对象
Joinpoint(连接点):程序执行过程中的某个特定的点
Advice(通知):在切面的某个特定的连接点上执行的动作
Pointcut(切入点):匹配连接点的断言,在AOP中通知和一个切入点表达式关联
Introduction(引入):在不修改类代码的前提下,为类添加新的方法和属性
Target Object(目标对象):被一个或者多个切面所通知的对象
AOP Proxy(AOP代理):AOP框架创建的对象,用来实现切面契约(aspect contract)(包括通知方法执行等功能)
Weaving(织入):把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象,分为:编译时织入、类加载时织入、执行时织入
Advice的类型
Before advice(前置通知):在某连接点(join point)之前执行的通知,但不能阻止连接点前的执行(除非它抛出一个异常)
After returning advice(返回后通知):在某连接点(join point)正常完成后执行的通知
After throwing advice(抛出异常后通知):在方法抛出异常退出时执行的通知
After(finally)advice(后通知):当某连接点退出的时候执行的通知(不管正常返回还是异常退出)
Around Advice(环绕通知):包围一个连接点(join point)的通知
Spring AOP默认使用标准的JavaSE动态代理作为AOP代理,这使得任何接口(或者接口集)都可以被代理
Spring AOP中也可以使用CGLIB代理(如果一个业务对象并没有实现一个接口)
简化的Proxy定义:使用福字bean定义,以及内部bean定义
Spring所有的切面和通知其都必须放在一个<aop:config>内(可以配置包含多个<aop:config>元素),每一个<aop:congif>可以包含pointcut,advisor和aspect元素(它们必须按照这个顺序进行声明)
Introductions
简介允许一个切面声明一个实现指定接口的通知对象,并且提供了一个接口实现类来代表这些对象
由<aop:aspect>中的<aop:declare-parents>元素声明该元素用于声明所匹配的类型拥有一个新的parent(因此得名)
schema-defined aspects只支持singleton model
Advisors
advisor就像一个小的自包含的方面,只有一个advice
切面自身通过一个bean表示,并且必须实现某个advice接口,同时,advisor也可以很好的利用AspectJ的切入点表达式
Spring通过配置文件中<aop:advisor>元素支持advisor实际使用中,大多数情况下它会和transactional advice配合使用
为了定义一个advisor的优先级以便让advice可以有序,可以使用order属性来定义advisor的顺序
ProxyFactoryBean
使用ProxyFactoryBean或者其它IoC相关类来创建AOP代理的最重要好处是通知和切入点也可以由IoC来管理
被代理类没有实现任何接口,使用CGLIB代理,否则JDK代理
通过设置proxyTargetClass为true,可强制使用CGLIB
如果目标类实现了一个(或者多个)接口,那么创建代理的类型将依赖ProxyFactoryBean的配置
如果ProxyFactoryBean的proxyInterfaces属性被设置为一个或者多个全限定接口名,基于JDK的代理将被创建
如果ProxyFactoryBean的proxyInterfaces属性没有被设置,但是目标类实现了一个(或者更多)接口,那么ProxyFactoryBean将自动检测到这个目标类已经实现了至少一个接口,创建一个基于JDK的代理
如果想,可以强制在任何情况下使用CGLIB,即使有接口
CGLIB代理的工作原理是在运行时生成目标类的子类,spring配置这个生成的子类委托方法调用到原来的目标
子类是用来实现Decotator模式,织入通知
CGLIB的代理对用户是透明的,需要注意:
final方法不能被通知,因为它们不能被覆盖
不用把CGLIB添加到classpath中,在Spring的JAR中有
aspect
@AspectJ切面使用@Aspect注解配置,拥有@Aspect的任何bean将被Spring自动识别并应用
用@Aspect注解的类可以有方法和字段,他们也可能包括切入点(pointcut),通知(Advice)和引入(introduction)声明
@Aspect注解是不能够通过类路径自动检测发现的,所以需要配合使用@Component注释或者在xml配置bean
pointcut
一个切入点通过一个普通的方法定义来提供,并且切入点表达式使用@Pointcut注解,方法返回类型必须为void
切入点表达式可以通过&&、||、和!进行组合,也可以通过名字引用切入点表达式
一个号的切入点应该包括以下几点:
选择特定类型的连接点,如:execution,get,set,call,handler
确定连接点范围,如:within,withincode
匹配上下文信息,如:this,target,@annotation
Around advice
环绕通知使用@Around注解来声明,通知方法的第一个参数必须是ProceedingJoinPoint类型
在通知内部调用ProceedingJoinPoint的proceed()方法会导致执行真正的方法,传入一个Object[]对象,数组中的值将会被作为参数传递给方法
切面实例化模型
"perthis"切面通过制定@Aspect注解perthis子句实现
每个独立的service对象执行时都会创建一个切面实例
service对象的每个方法在第一次执行的时候创建切面实例,切面在service对象失效的同时失效
本文出自 “11828641” 博客,请务必保留此出处http://11838641.blog.51cto.com/11828641/1897579
原文:http://11838641.blog.51cto.com/11828641/1897579