Spring学习中,有些许零散知识点涉及一些细节,稍作整理算是回顾。
1:Spring中的两大核心概念IOC&&AOP:
1.1:IOC(DI):Inversion of Control(Dependency Injection),说的就是在容器启动之后,会初始化很多的bean对象,而对象与对象之间的关系,是依赖于容器完成设置的,而在Spring方法之前,我们是要通过使用Set方法来手动的设置的。也就是将设置依赖的控制转到了Spring容器那里去了。不用我们手动去控制了。
1.2:AOP(Abstract Oriented Programming):面向抽象编程,也叫做面向切面编程,这样可以很好的保持程序的灵活性,特别是在用spring控制事务的时候,尤其有用。
2:IOC中的三大类注入类型(setter注入,构造注入,接口注入(属性注入)):
2.1:setter方法注入,这是最常用的注入方式:
Xml方式代码如下:
<bean id="u" class="com.zxb.dao.impl.UserDAOImpl">
</bean>
<bean id="userService" class="com.zxb.service.UserService">
<property name="userDAO" ref="u" />
</bean>
如上所示:XML方式不需要再java类代码中做任何修改(但需保证在UserService类中有一个setUserDAO的方法),只需配好bean即可,这样就可以将id为u的bean注入到id为userService的bean中。
2.2:构造方法注入,很少使用。
这种注入方式,就是在UserService这个类中有一个构造方法,其中要传入一个UserDao对象。这就可以通过这种注入方式来完成。
注意<constructor-arg>可以加入type后者index属性类来指定为构造方法中的参数添加类型限制或者索引限制,比如当前bean要注入到方法的第几个参数,后者第几个参数必须是什么类型的等等。
Xml方式代码如下:
<bean id="u" class="com.zxb.dao.impl.UserDAOImpl">
</bean>
<bean id="userService" class="com.zxb.service.UserService">
<constructor-arg><ref bean="u"/></constructor-arg>
</bean>
或者是(下面这种方式每次都创建一个新的待注入对象):
<bean id="u" class="com.zxb.dao.impl.UserDAOImpl">
</bean>
<bean id="userService" class="com.zxb.service.UserService">
<constructor-arg><bean class="com.zxb.impl.UserDaoImpl"></constructor-arg>
</bean>
2.3:接口注入(属性注入):
这种方式在Annotation方式中就是直接在类的private Type 属性上加入注入注解,此时连private属性的getter,setter方法都可以不要就可以把值注入进来,虽然可行,但是破坏了类的封装性,故基本不用。
这里补充一个问题:声明一个bean的时候,指定属性id="xxx"或者指定属性name=“yyy”都可以,那么他们之间有什么区别呢?区别就是:当使用name指定的时候,name的值可以使特殊字符。而id是不允许出现特殊字符的。
3:简单属相和集合属性注入注入:
简单属性注入代码如下所示:
<bean id="userService" class="com.zxb.service.UserService">
<property name="String" value="StringValue" />
</bean>
一般而言,很少会使用简单属性注入,或者是基本不用,因为简单属性一般都是直接在程序中设定,而在使用Spring自己提供的一些类的时候,可能会用到简单属性的注入,比如说使用Spring配置DataSource的时候,要配置数据源的一些相关属性,这个时候,就有很多简单属性要设置了。
集合属性注入代码示例如下(很简单,直接从Spring文档中Copy过来的):
<bean id="moreComplexObject" class="example.ComplexObject">
<!-- results in a setAdminEmails(java.util.Properties) call -->
<property name="adminEmails">
<props>
<prop key="administrator">administrator@example.org</prop>
<prop key="support">support@example.org</prop>
<prop key="development">development@example.org</prop>
</props>
</property>
<!-- results in a setSomeList(java.util.List) call -->
<property name="someList">
<list>
<value>a list element followed by a reference</value>
<ref bean="myDataSource" />
</list>
</property>
<!-- results in a setSomeMap(java.util.Map) call -->
<property name="someMap">
<map>
<entry key="an entry" value="just some string"/>
<entry key ="a ref" value-ref="myDataSource"/>
</map>
</property>
<!-- results in a setSomeSet(java.util.Set) call -->
<property name="someSet">
<set>
<value>just some string</value>
<ref bean="myDataSource" />
</set>
</property>
</bean>
在我们定义一个bean的时候,可以使用@Scope("XX")或者在XML中定义bean的时候指定scope="xx"来指定bean的生存范围:总共有如下五个:
4.1:Singleton:单例,即系统始终只有一个bean实例。
4.2:ProtoType:原型,即每次请求都会产生一个新的Bean实例。
4.3:request:在J2EE中使用,对于每次对于此bean类的请求,都将产生一个新的bean实例。
4.4:session:在J2EE总使用,对应于每次会话产生一个实例。
4.5:global Session:在J2EE中使用,对应于一个Application产生一个实例。
5:自动装配:
原来bean的注入需要我们在xml中使用<property name="xxx" ref="xxx"/>的方式注入,或者在Annotation中使用@Resource等注入,而自动装配就是说这些工作我们都不用自己做了,可以让Spring来帮我们完成。
方式一:在<beans>中使用属性default-autowired="byName或者byType"来指定全局的自动属性注入策略。
方式二:为每一个<bean>添加属性autowire=“byName或者byType”来指定此类的属性注入策略。注意,默认的autowire属性设置为no,即需要手动的注入。
代码如下(如下所示:当要为userService注入属性userDAO的时候,会依据其属性自动在IOC容器中找到正确类型的Bean给注入进来。):
<bean id="u" class="com.zxb.dao.impl.UserDAOImpl">
</bean>
<bean id="userService" class="com.zxb.service.UserService" autowire="byType">
<!-- <property name="userDAO" ref="u" /> -->
</bean>
当一个IOC容器中有很多的bean实例要实例化的时候,如果在容器一启动就开始实例化,势必会很影响性能,如果我们让bean在用到的时候在初始化,这样可以很大程度上提升性能。这可以通过设置bean 的lazy-init属性为true实现。当然,也可以在<beans>标签中设置全局的属性defaule-lazy-init来实现全局控制,如下所示:
<bean id="u" class="com.zxb.dao.impl.UserDAOImpl" lazy-init="true">
7:init-method(@postConstruct)与destroy-method(@PreDestroy):
在xml中的bean标签中设置属性init-method="methodName"或者在类中的某个方法上加入@postConstruct注释,表明这个方法是在这个类的实例被容器实例化后要调用的方式。而destroy_method(@PostDestory)则是在bean实例要销毁之前要执行的方法,这在日志记录中很常用。
8:如何设置才可以在Spring中使用Annotation?
首先要引入相关的jar包。然后要配置xml的配置文件,引入相关的命名空间设置。最为重要的是要配置一句<context:annotation-config/>,因为就是这一句话,spring内部就帮我们初始化了四个核心bean,然后通过这四个核心的bean去处理我们程序中的Annotation。然后我们还要告诉Spring,这四个核心bean应该去程序中那些位置区寻找我们的Annotation。这个时候就要配置我们的<context:component-scan base-package="xxx.xxxx.xxx"/>。
实例代码如下:
<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-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.zxb"/>
</beans>
这样设置了以后,就可以在这里面不设置任何bean了,然后全部在程序中加Annotation对bean进行标识。
9:常用的几个Annotation总结:
9.1:@Scope(“xxxx”):设置在类上面,表明该bean的生存范围。
9.2:@Component("xxxx"):消除了对于xml文件的依赖,设置在类上面,表明这是一个bean实例。
9.3:@autowired:最好设置在set方法上,用来实现依赖注入,默认是byType。
9.4:@Resource:最好设置在set方法上,用来实现依赖注入,默认是byName,如果没有匹配的名字,就会按byType机制实现注入。
9.5:@qualifier:比如在xml中设置了类型A的两个bean,分别为u1,u2,这个时候,如果用@autowired给B注入一个A的bean时候,就会发生错误,因为不知道该注入到底哪个, 这个时候,我们可以给参数加上一个@qualifier注释,直接告诉到底要注入哪个bean元素。
9.6:required:用来告诉容器,此属性必须注入,用来容错使用的,作用和@Override极为相似。
10:@Component、@Service、@Repositry、@Controller区别。
首先,这四个Annotation在Spring框架中都是用来标记一个类作为一个bean实例的,@Component是一个通用的Annotation,其他三个Annotation的不同之处在于和@Component相比,他们是在特殊情况下的@Component的变体特殊化使用,说白了,其实还是@Component,而且这种区别仅仅是分类级别。从技术上说,这四个Annotation的核心目的一样。
其最主要的区别在于他们分别用于不同的类的定义中,一个大型系统中,系统分为好多层,我们可以分别用这四个annotation来标记不同的层。
@Component:最通用的注解,在整个应用中不管什么层的类都可以使用。
@Service:标记Service层的类
@Controller:标记表现层的类,主要用在Spring MVC中,在Struts的Action可以用这个注释来进行标记。
@Repository:标记持久层的类,这些类都是与数据的存储有关的,比如说DAO层的类。
既然这四个注释基本没有区别,那为什么还设置四个呢?其实,将来,Spring可能会选择给@Service、@Controller、@Repository基于他们所处的层次约定来添加一些控制值,出于对于将来的考虑,最好还是遵从这种约定并且合理在各个层中使用他们。