java初入之spring框架
Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架
控制反转:类的实例和生命周期的管理交由外部容器(spring)来实现;
轻量级、重量级的定义:
一个框架的轻重量级,是由该框架启动的服务来定义的,启动的服务多,对应用的性能消耗就会多,就属于重量级的框架,反之就是轻量级的框架;
spring的配置文件(获取spring对象时需要此配置文件)
Spring 的引入,下载jar包或者在xml文件中注入;
Spring的使用之配置文件:
<?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-2.5.xsd">
</beans>
在xml文件的bean容器中将类交给spring管理
ForE: <bean id = "xxxInterface" class="packagePath"+".className" scope=""></bean>
id:通过spring容器获得类的实例时候的标识;
class : 要实例的类;
scope : 类的作用范围,singleton ,单例模式,一个Spring的容器中只存在一个类的实例;
propotype ,每次请求都会返回一个新的实例
在xml文件中在一个类中注入另一个类的引用
ForE:<bean id="secondinterface" class="impl.SecondInterfaceImpl">
<constructor-arg index="0" ref="firstinterface"/>
</bean>
<bean id="firstinterface" class="impl.FirstInterfaceImpl"></bean>
方法一:通过构造函数注入
SecondInterfaceImpl(FirstInterface mFirstInterface){
this.mFirstInterface=mFirstInterface;
}
如果做了上面的配置,Spring在实例化SecondInterface的时候,会将FirstInterface的实例注入到构造方法中
方法二:通过set方法注入
<bean id="secondinterface" class="impl.SecondInterfaceImpl">
<property name="mFirstInterce" ref="firstinterface"/>
</bean>
<bean id="firstinterface" class="impl.FirstInterfaceImpl"></bean>
在SecondInterface中声明FirstInterface的set方法
public void setmFirstInterface(FirstInterface mFirstInterface) {
this.mFirstInterface = mFirstInterface;
}
同样可以将FirstInterface的实例注入到SecondInterface中
bean的生命周期方法
(init-method、destroy-method)
<bean id="firstinterface" class="impl.FirstInterfaceImpl" init-method="init" destroy-method="stop"></bean>
这样配置之后,通过ClassPathApplicationContext调用getBean()实例化类的时候,会首先调用FirstInterface的init()方法,同事调用destroy()方法之前会调用FirstInterface的stop方法
全局配置(default-init-method/default-destroy-method)
<beans
...
default-init-method="init"
default-destroy-method="destroy"
></beans>
这样声明之后,beans下所有的bean声明的类都会调用各自的init和destroy方法
继承InitializingBean/DisposableBean接口
如果类继承了InitializingBean接口,会重写afterPropetiesSet()方法,此方法会在spring实例化类之前调用
如果继承了DisposableBean接口,会复写destroy()方法,此方法会在spring调用自己的destroy之前调用;
优先级 实现接口>init-method/destroy-method>default-init-method/default-destroy-method
XXXAware接口
Spring提供了以Aware为结尾的一系列接口,方便我们可以拿到spring的一些资源
ForE:
ApplicationContextAware接口,实现此接口会复写setApplicationContext(ApplicationContext context)方法,此方法可以拿到spring的上下文
BeanNameAware 接口,实现此接口会复写setBeanName(String str)方法,str表示的xml文件中配置的bean的id(注:谁实现的此接口,name就表示谁的id)
总的来说,感觉没啥用,自己配的难道不知道么,0_0!!!!
自动装配
所谓的自动注入,就是通过配置属性的方法,有Spring在配置文件中寻找相应的类进行注入,不需要通过在bean中配置propoty或是constructor-arg;
1)<beans
...
default-autoware="byName"
></beans>
此配置会根据要实现注入的类中成员的名称为标准,一一比对xml文件中的id属性,有相同的就会将实例注入
如SecondInterface 中有一个成员
public FirstInterface mFirstInterface;
public void SetFirstInterface(FirstInterface mFirstInterce){}
<bean id="secondinterface" class="...SecondInterfaceImpl">
<bean id="mFirstInterface" class="...FirstInterfaceImpl">
这样就可以实现将FirstInterface的实例注入到SecondInterface中,注意成员变量名和id的名称要一致;
2)<beans
...
default-autoware="byType"
></beans>
实现方法和byName一致,不过set()方法要注入的实例是根据class属性来查找的
3)<beans
...
default-autoware="constructor"
></beans>
通过构造器注入,顾名思义,根据构造方法实现的注入,构造方法要注入的实例也是根据class属性来查找的;
Resource
ApplicationContext 实现了ResourceLoader接口,因此可以调用getResource(String path)方法,读取一些资源文件(ApplicationContext可以实现 ApplicationContextAware接口获得)
getResource("classpath*:"+xxx)
getResource("file:"+绝对路径(ForE D:\xxx\xxx));
getResource("url:"+网络路径)
getResource(xxx),这样写默认的是与ApplicationContext的创建方式一样的(new ClassPathApplicationContext("classpath*:"+xxx)),这样默认的也是根据classpath来的
注解篇:
要是用注解,首先需要在xml文件中进行配置
<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="packageName"/>
</beans>
这样配置之后Spring会扫描packageName包下的类,查看其是否有注解,有就进行管理
配置文件:xsi:schemaLocation 配置的路径是与命名空间对应的schema文件装载路径
针对类
@Component/是一个泛化的概念,仅仅表示一个组件 (Bean) ,可以作用在任何层次
@Service/通常作用在业务层,但是目前该功能与 @Component 相同
@Controller/通常作用在控制层,但是目前该功能与 @Component 相同
上面三个注解都是将类交给Spring进行管理,与在xml中申明bean效果是一样的,没个注解都有name属性,类似xml的id属性
@scope("prototype/singleton")申明类的实例类型,单例还是工厂
针对类中
@Required 用于setter方法,此注解表示的方法,注入的对象不能为空,否则会抛异常
@Autowired(和@Inject等价) 用于set方法,成员变量和构造器,此注解标注的方法,注入的对象默认不能为空,为空抛异常,要想不抛异常,使用 @Autowired(requred=false)
注意:使用@Autowired时,每个类只能有一个构造器标注为requred=true,不过Requred=true时,建议使用Requred惊醒注解;
@PostConstruct 在类初始之前执行某个方法 @PreDestroy 在类销毁前执行某个方法;
AOP(Aspect Oriented Programming)面向切面编程
AOP的两种实现方式:预编译和运行期动态代理
概念
切面:贯穿多个业务功能(体现在代码中就是多个业务类)关注点;
连接点(Joinpoint):程序执行过程中的某一步;
通知:(在连接点上进行的操作)
前置通知:连接点代码执行前进行的操作,不能阻止连接点的执行,除非抛异常
异常通知:连接点代码运行异常后执行的操作
返回后通知:连接点代码顺利执行完毕后进行的操作
后通知:连接点代码执行后的操作,不管顺利执行还是抛异常
环绕通知:包围一个连接点的通知
切入点:匹配到的连接点
引入(Introduction):再不修改代码的前提下添加新的属性或方法
目标对象:通知的对象
AOP代理:AOP框架创建的对象
织入(Weaving):把切面关联到业务功能的对象或者业务类上,并创建一个目标对象,分为编译时织入,类加载时织入和执行时织入
AOP配置之xml篇
<bean id="aspectClass" class = "xxx"/>
<bean id="pointCutClass" class = "xxx"/>
<aop-config>
<aop-aspect id="myAOPAspect" ref="aspectClass">
<aop:pointcut expression="execution(*impl.FirstInterface*(..))" id="myPointCut">
<aop:before method="before" pointcut-ref="myPointCut">
<aop:after-returning method="afterReturn" pointcut-ref="myPointCut">
<aop:after-throwing method="afterThrowing" pointcut-ref="myPointCut">
<aop:after method="After" pointcut-ref="myPointCut">
</aop-aspect>
</aop-config>
aop-aspect ref 指定的是切面(类),aop:before/after等指定的方法都必须在此类中存在
aop:pointcut expression属性制定的是切点格式execution(* packageName.className.MethodName||*(..))后一种方法表示所有的方法都会执行拦截通知
循环通知:aop-around
aop-around 制定的方法,必须有一个参数(且必须是第一个)ProceedingJoinPoint,这个参数有一个方法proceed(),调用这个方法,就会执行切入点的方法的代码,因此,可以在业务代码执行前后进行一些操作;
ForE: <aop-around method="aroundMethod" pointcut-ref="..."/>
public void aroundMethod(ProceedingJoinPoint joinPoint,String name,int age){
Syso.("业务代码执行前");
joinPoint.proceed();
Syso.("业务代码执行后");
}
业务代码方法的参数,可以通过在环绕通知方法后面追加同类型的参数传递过来
Introduction:让制定的类,强制实现一个接口(强制给他一个爸爸)
ForE:
<aop:declare-parents
types-matching="impl.*(+)"
implement-interface="impl.xxxInterface"
default-impl="impl.xxxInterfaceImpl"/>
这样申明之后,所有的impl包下的类都会实现xxxInterface接口,xxxInterface有一个默认的实现类xxxInterfaceImpl,避免调用接口方法时异常;
浙公网安备 33010602011771号