控制反转
应用本身不负责依赖对象的创建以及维护,依赖对象的创建及维护都是由外部容器负责。这样控制权就由应用转移到外部容器,控制权的转移就是所谓的反转。
轻量级与重量级概念的划分
主要看它使用了多少服务.使用的服务越多,容器要为普通java对象做的工作就越多,必然会影响到应用的发布时间或者是运行性能.
对于spring容器,它提供了很多服务,但这些服务并不是默认为应用打开的,应用需要某种服务,还需要指明使用该服务,如果应用使用的服务很少,如:只使用了spring核心服务,那么我们可以认为此时应用属于轻量级的,如果应用使用了spring提供的大部分服务,这时应用就属于重量级。目前EJB容器就因为它默认为应用提供了EJB规范中所有的功能,所以它属于重量级。
使用Spring需要的jar
dist\spring.jar
lib\jakarta-commons\commons-logging.jar
如果使用了切面编程(AOP),还需要下列jar文件
lib/aspectj/aspectjweaver.jar和aspectjrt.jar
lib/cglib/cglib-nodep-2.1_3.jar
如果使用了JSR-250中的注解,如Resource/PostConstruct/PreDestroy,还需要下列jar文件
lib\j2ee\common-annotations.jar
实例化Spring容器常用的两种方式:
(1)1在类路径下寻找配置文件来实例化容器
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"beans.xml"});
(2)在文件系统路径下寻找配置文件来实例化容器
ApplicationContext ctx = new FileSystemXmlApplicationContext(new String[]{“d:\\beans.xml“});
从spring容器中得到bean
当spring容器启动后,因为spring容器可以管理bean对象的创建,销毁等生命周期,所以我们只需从容器直接获取Bean对象就行,而不用编写一句代码来创建bean对象。从容器获取bean对象的代码如下:
ApplicationContext ctx = new ClassPathXmlApplicationContext(“beans.xml”);
HelloWorld h = (HelloWorld)ctx.getBean("hello");
或者
HelloWorld h = (HelloWorld)ctx.getBean("hello",HelloWorld.class);
三种实例化bean的方式
1.使用类构造实例化
2.使用静态工厂方法实例
3.使用实例工厂方法实例化
依赖注入
使用构造器注入
使用属性setter方法注入
使用Field注入(用于注解方式)
装配依赖对象
手工装配依赖对象,在这种方式中又有两种编程方式。
1. 在xml配置文件中,通过在bean节点下配置。
2.在java代码中使用Autowired或Resource注解方式进行装配。
手工装配
在java代码中使用Autowired或Resource注解方式进行装配,这两个注解的区别是:Autowired默认按类型装配,Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。
Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false。如果我们想使用按名称装配,可以结合Qualifier注解一起使用。
Resource注解和Autowired一样,也可以标注在字段或属性的setter方法上,但它默认按名称装配。名称可以通过Resource的name属性指定,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。
果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时, @Resource注解会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了
自动装配依赖对象
<bean id="..." class="..." autowire="byType"/>
autowire属性取值如下:
byType:按类型装配,可以根据属性的类型,在容器中寻找跟该类型匹配的bean。如果发现多个,那么将会抛出异常。如果没有找到,即属性值为null。
byName:按名称装配,可以根据属性的名称,在容器中寻找跟该属性名相同的bean,如果没有找到,即属性值为null。
constructor与byType的方式类似,不同之处在于它应用于构造器参数。如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。
autodetect:通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现默认的构造器,那么将使用byType方式。
把组件纳入spring容器中管理
Service用于标注业务层组件、 Controller用于标注控制层组件(如struts中的action)、Repository用于标注数据访问组件,即DAO组件。而Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
在一个稍大的项目中,通常会有上百个组件,如果这些这组件采用xml的bean定义来配置,显然会增加配置文件的体积,查找及维护起来也不太方便。spring2.5为我们引入了组件自动扫描机制,他可以在类路径底下寻找标注了Component、Service、Controller、Repository注解的类,并把这些类纳入进spring容器中管理。它的作用和在xml文件中使用bean节点配置组件是一样的。
@Autowired
默认按类型by type
如果想用byName,使用@Qulifier
写在private field(第三种注入形式)(不建议,破坏封装)
如果写在set上,@qualifier需要写在参数上
@Resource(重要)
加入:j2ee/common-annotations.jar
默认按名称,名称找不到,按类型
可以指定特定名称
推荐使用
不足:如果没有源码,就无法运用annotation,只能使用xml
@Component @Service @Controller @Repository
可以指定初始化bean的名字
@PostConstruct = init-method; @PreDestroy = destroy-method;
AOP中的概念
Aspect (切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面横切性关注点的抽象.
joinpoint (连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器)
Pointcut (切入点):所谓切入点是指我们要对那些joinpoint进行拦截的定义.
Advice (通知):所谓通知是指拦截到joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知
Target (目标对象):代理的目标对象
Weave (织入):指将aspects应用到target对象并导致proxy对象创建的过程称为织入.
Introduction (引入):在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.
使用Spring进行面向切面(AOP)编程
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
</beans>
步骤:
1.加上对应的xsd文件spring-aop.xsd
2.beans.xml <aop:aspectj-autoproxy />
3.此时就可以解析对应的Annotation了
4.建立我们的拦截类
5.用@Aspect注解这个类
6.建立处理方法
7.用@Before来注解方法
8.写明白切入点(execution …….)
9.让spring对我们的拦截器类进行管理@Component
常见的Annotation:
a)@Pointcut 切入点声明 以供其他方法使用 ,
b)@Before 发放执行之前织入
c)@AfterReturning 方法正常执行完返回之后织入(无异常)
d)@AfterThrowing 方法抛出异常后织入
e)@After 类似异常的finally
f)@Around 环绕 类似filter
基于注解方式声明切面
首先启动对@AspectJ注解的支持(蓝色部分):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<aop:aspectj-autoproxy/>
<bean id="orderservice" class="cn.itcast.service.OrderServiceBean"/>
<bean id="log" class="cn.itcast.service.LogPrint"/>
</beans>
基于注解方式声明切面
public class LogPrint {
@Pointcut("execution(* cn.itcast.service..*.*(..))")
private void anyMethod() {}//声明一个切入点
@Before("anyMethod() && args(userName)")//定义前置通知
public void doAccessCheck(String userName) {
}
@AfterReturning(pointcut="anyMethod()",returning="revalue")//定义后置通知
public void doReturnCheck(String revalue) {
}
@AfterThrowing(pointcut="anyMethod()", throwing="ex")//定义例外通知
public void doExceptionAction(Exception ex) {
}
@After("anyMethod()")//定义最终通知
public void doReleaseAction() {
}
@Around("anyMethod()")//环绕通知
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
return pjp.proceed();
}
}
基于基于XML配置方式声明切面
public class LogPrint {
public void doAccessCheck() {}定义前置通知
public void doReturnCheck() {}定义后置通知
public void doExceptionAction() {}定义例外通知
public void doReleaseAction() {}定义最终通知
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
return pjp.proceed();环绕通知
}
}
基于基于XML配置方式声明切面
bean id="orderservice" class="cn.itcast.service.OrderServiceBean"/>
<bean id="log" class="cn.itcast.service.LogPrint"/>
<aop:config>
<aop:aspect id="myaop" ref="log">
<aop:pointcut id="mycut" expression="execution(* cn.itcast.service..*.*(..))"/>
<aop:before pointcut-ref="mycut" method="doAccessCheck"/>
<aop:after-returning pointcut-ref="mycut" method="doReturnCheck "/>
<aop:after-throwing pointcut-ref="mycut" method="doExceptionAction"/>
<aop:after pointcut-ref="mycut" method=“doReleaseAction"/>
<aop:around pointcut-ref="mycut" method="doBasicProfiling"/>
</aop:aspect>
</aop:config>