spring
spring概要:
bean
1、bean元素的scope属性(生命周期)
(1)singleton 默认值
单例对象 :被标识为单例的对象在spring容器中只会存在一个实例
(2)prototype
多例原型:被标识为多例的对象,每次在获得才会被创建,每次创建都是新的对象
(3)request
Web环境下,对象与request生命周期一致
(4)session
Web环境下,对象与session生命周期一致
singleton 只有一个实例,也即是单例模式。
prototype访问一次创建一个实例,相当于new
2、<beans>可以分模块化配置(导入其他的Spring配置文件)
<beans>
<import resource = “spring配置文件的全路径名” />
</beans>
3、spring三种对象的创建方式
空参数构造
静态工厂创建
<bean name="user" class="cn.itcats.UserFactory" factory-method="createUser"></bean>
实例工厂创建
<bean name="user2" factory-bean="userFactory" factory-method="createUser"></bean>
由于不能用类直接调用非静态方法所以需要创建工厂bean
<bean name=“userFactory” class=“cn.itcats.UserFactory”></bean>
(Spring注入方式参见Spring DI.txt)
4、Spring整合Junit
@RunWith(SpringJUnit4ClassRunner.class) //帮我们创建容器
@ContextConfiguration("classpath:applicationContext.xml") //指定创建容器时候的具体配置文件
此时容器已经创建完毕
5、Spring 整合 JDBC
spring中提供了一个可以操作数据库的对象,对象封装了jdbc技术 ————JDBCTemplate JDBC模板对象
而JdbcDaoSupport则对JdbcTemplate进行了封装,所以要操作JdbcTemplate,或只需要继承JdbcDaoSupport即可。
spring DI
以下都是XML注入方式:
1、 有参构造方法注入
constractor-arg type/index
2、 setter()方法注入
必须有一个无参构造方法
property name value/ref
name 与setName()对应
3、 函数注入:
p命名空间注入 applicationContext.xml中<beans>标签头部导入p命名空间
书写格式:值类型注入—— p:属性名="值" 引用类型注入—— p:属性名-ref="引用的<bean> name属性"
<bean name="run2" class="cn.itcats.thread.Run" p:name="haha" p:age="20" p:hello-ref="hello"></bean>
spel注入: spring Expression Language spring表达式语言
<bean name="runSpel" class="cn.itcats.thread.Run">
<property name="name" value="#{user.name}"></property>
</bean>
3、 bean对象的创建:
bean对象一般在需要的时候才会被创建。在创建之前,bean属性不会被配置。
singleton bean会在容器创建的时候同时创建。
在beaan创建的时候,依赖的其他bean也要被创建
即使Spring容器被正确加载,在创建bean时,如果属性和依赖关系发生错误,依旧会抛出异常
4、采用singleton模式 单例
缺点:会加大容器创建时的内存开销
优点:ApplicationContext被加载的时候可以尽早的发现一些配置的问题
5、 bean A对bean B存在依赖关系,那么Spring IoC容器在调用bean A的setter方法之前,bean B必须被完全配置,这里所谓完全配置的意思就是bean将被实例化(如果不是采用提前实例化的singleton模式),相关的依赖也将被设置好。
注意循环依赖异常(bean A 和 bean B 相互依赖)
6、 idref 用于将其他bean 的id 传给constractor-arg property参数
使用idref 的好处:idref 可以在容器创建的时候进行依赖检验,不至于在bean被实例化的时候才发现依赖错误。
7、引用bean的方式:
<ref bean="student"> 可以引用同一容器和父容器中的bean(不一定在一个XML文件中)(student 可以实id 或者 name)
<ref local="student"> 可以引用本地容器(同一个XML文件中的bean)(student 只能是id)
<ref parent="student"> 可以引用父容器中的bean(student 可以实name\ id)
8、集合装配:
<list/> <set/> <map/> <props/>标签可以设置和定义Java Collection类中的List Set Map Properties类的值。
注意不同标签的不同语法
以下都是注解注入方式:
1、使用注解方式时,必须在spring配置文件的schema中添加注解的命名空间和与schemaLocation
2、注释本身是不会做任何事情的,它仅提供元数据信息。用处理器来处理元数据。所以我们还需要在spring配置文件中注册注解处理器,这样Spring容器才对会bean之间的依赖进行注入,该标签<context:annotation-config />需要在<bean>元素之前添加。完成以上步骤后,我们只需在配置文件配置bean即可,而不用再配置对象之间的依赖关系。
3、注入方式:
值类型的注入:
实际上通过反射注入:
@Value("tom")
private String name;
实际上通过set方法注入:
@Value("tom")
public void setName(String name){
this.name = name;
}
引用类型的注入:
@Autowired 可以注解在属性、setter方法、 构造器上 按照类型装配依赖对象,默认指定的依赖对象要存在,可更改
@Qualifier("id") 在存在多个同类型的bean 的时候指定对应bean 对象 标注对象是属性、方法入参、构造入参
例如在Student类下:
@Autowired
public void setBicycle(@Qualifier("bicycle")Bicycle bicycle) {
this.bicycle = bicycle;
JSR-250 的注解:
@Resource
@Resource 默认按照名称策略注入,也可以按照类型注入。Spring将@Resource注解的name属性解析为bean对象的id或则name,将type属性解析为bean的类型,进而实现自动注入
如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象
@AutoWired(required=false) + @Qualifier("user") == @Resource(name="user")
@PostConstruct 和 @PreDestroy
JSR-250 为初始化之后/销毁之前方法的指定定义了两个注释类,分别是 @PostConstruct 和 @PreDestroy。这两个注解只能应用于方法上。与xml配置方式不同的是,@PostConstruct 和 @PreDestroy可以指定多个
@PostConstruct 在类实例化之后调用
@PreDestroy 在类销毁之前调用
组件注解:
通过注释定义 Bean,从 XML 配置文件中完全移除 Bean 定义的配置
组件自动扫描机制:在类路径底下寻找标注了@Component、@Service、@Controller、@Repository注解的类,并把这些类纳入进spring容器中管理。
要使用@Component注解,Spring容器必须启用类扫描机制以启用注释驱动 Bean 定义和注释驱动 Bean 自动注入的策略。
<context:component-scan base-package="org.spring.annotation" /> 其中base-package为需要扫描的包(含子包)。
这时Student类
@Component
public class Student {
@Resource
private Bicycle bicycle;
public Bicycle getBicycle() {
return bicycle;
}
}
Bicycle类
@Component
public class Bicycle {
}
spring AOP
Spirng AOP 切面编程
使用aop需要用到的包:spring-aop + spring-aspects + springsource.org.aopalliance + springsource.org.aspectj.weaver
1、 名词解释:
JoinPoint(连接点):目标对象中,所有可以增强的方法,就是spring允许你是通知(Advice)的地方,那可就真多了,基本每个方法的前、后(两者都有也行),或抛出异常是时都可以是连接点,spring只支持方法连接点。
Pointcut(切入点):目标对象中,已经被增强的方法。调用这几个方法之前、之后或者抛出异常时干点什么,那么就用切入点来定义这几个方法。
Advice(通知/增强):增强方法的代码、想要的功能。
Target(目标对象):被代理对象,被通知的对象,被增强的类对象。
Weaving(织入):将通知应用到连接点形成切入点的过程
Proxy(代理):将通知织入到目标对象之后形成的代理对象
aspect(切面):切入点+通知————通知(Advice)说明了干什么的内容(即方法体代码)和什么时候干(什么时候通过方法名中的before,after,around等就能知道),二切入点说明了在哪干(指定到底是哪个方法),切点表达式等定义。
2、
基于XML:
准备目标对象(User UserImpl以及几个方法)
准备通知(Myadvice类 public void before() after() afterRunning() around() afterException() )
配置applicationContext.xml
1.导入命名空间
2.配置目标对象
<bean name= class= ></bean>
3.配置通知对象
<bean name= class= ></bean>
4.配置将通知织入目标对象
<aop:config>
<aop:pointcut expression="expression()" id="" >
<aop:aspect ref="">
<aop:before method="" pointcut="">
<aop:around method="" pointcut="">
</aop:aspect>
</aop:config>
基于Annotation:
1.applicationContext.xml中配置目标对象,通知对象,开启使用注解完成织入(<aop:aspectj-autoproxy></aop:aspectj-autoproxy>)
2.@Aspect注解代表定义一个切面(一般在通知和切入点的类上面),书写切点表达式@Pointcut("execution(返回值 全类名.方法名(参数))")
@Aspect
public class Myadvice{
@Pointcut("") //切入点也可以在其他类中
public void pc(){}
//前置通知
//@Before(execution(返回值 全类名.方法名(参数))
@Before("Myadvice.pc()")
public void before(){
sout("前置方法");
}
//环绕通知
@Around("Myadvice.pc()")
public void around(ProceedingJoinPoint proceedingJoinPoint){
//环绕方法执行前
//proceedingJoinPoint.proceed();表示对拦截的方法进行放行
//若注释proceedingJoinPoint.proceed()则不会执行被AOP匹配的方法
proceedingJoinPoint.proceed();
//环绕方法执行后
}
}
引用
它可以使代理对象实现一个给定的接口用来添加额外的方法或字段
@DeclareParents来定义一个引入,其中value表示要引入的目标对象,defaultImpl表示要实现接口的实现类的Class对象。
@DeclareParents(value="com.ctc.ServerImpl.*+", defaultImpl=Adult.class)
public static AgeGroup agegroup;