spring入门
Spring框架
入门:
IOC(控制反转,DI(依赖注入))
加载相应jar包或坐标(maven):spring-context,spring-core,spring-beans,spring-expression,commons-logging,lombok
写一个实体类。然后定义一个spring的xml文件,默认取名为applicationContext.xml
xml中:
<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="对这个bean取一个唯一名" class="全限定类名" scope="单例或多例模式" autowire="自动装配"> <property name="实体类的属性名" value="实体类相应属性的值"></property> <property name="实体类的属性名" ref="引用当前spring管理的对象"></property> (property是根据你实体类的set方法后跟的属性名来赋值的 例:setId(Interger id) 你的name填Id就会调用你的这个set方法而不是根据你的属性名 或者使用 <constructor-arg value="需要赋的值" index="第几个参数" type="参数类型"></constructor-arg> (构造方法注入) </bean> 如果加入了p命名空间,就可以直接使用p:属性名赋值 <bean id="唯一id值" class="全限定类名" p:属性名=""> <bean><property><bean>内部bean,可以看作局部变量</bean></property></bean> </beans>
Test类:
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");加载文件 World world = (实体类)ac.getBean("bean的id"); ac.getBean(class);要求bean管理的此类对象只有一个 ac.getBean("bean的id",class)第三种方法更加精确不需要强转类型
成功使用spring的容器加载类。这也就实现了所谓的IOC控制反转,将由程序控制管理的类交由Spring去管理,我们不需要关心它是如何被创建出来的
工厂bean模式:
public class MyFactory implements FactoryBean<World> { public World getObject() throws Exception { World world = new World(); world.setName("Hello World!"); return world; } public Class<?> getObjectType() { return World.class; } public boolean isSingleton() { return false; } }
继承FactoryBean,实现其中方法
<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="factory" class="com.spring.MyFactory"></bean> </beans>
配置文件改为得到这个工厂,然后同样测试就可以直接得到这个对象,这是工厂创建
bean的生命周期:通过容器或者工厂创建bean实例—为bean设置属性—调用初始化方法—bean可以使用—容器关闭并销毁bean
如果实现了BeanPostProcessor会增加两个时期,分别在bean实例初始化前后
加载外部配置文件
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"> <property name="location" value="classpath:"></property> </bean> 或 <context:property-placeholder location="classpath:"></context:property-placeholder>
通过注解标识组件
普通组件:@Component 持久层组件:@Repository 业务逻辑层:@Service 控制层:@Controller
? 需添加扫描
<context:component-scan base-package="相应包"> <context:include-filter type="annotation" expression="注解的全限定类名"/> <context:exclude-filter type="assignable" expression="类型的全限定类名"/> </context:component-scan>
@Autowired 自动装配。@Qqualifier(value="beanid")指定相应bean
AOP面向切面编程
之前我们业务代码中会有很多公共部分,一般会使用动态代理的方法从而实现从业务代码将公共功能抽取出来
oop:纵向继承机制 aop:横向抽取机制
横切关注点:从每个业务方法中抽取的非核心业务
切面:封装横切关注点信息的类,每个关注点体现为一个通知方法
通知:切面必须要完成的各个具体工作
目标:被通知的对象,作用到的对象
代理:向目标对象应用通知之后创建的代理对象
连接点:从横切关注点抽取的某个特定位置
切入点:找到相应连接点的位置,是一个条件。就好比数据库连接点是数据中的记录,切入点就是查询条件
加载相应jar包或坐标(maven):spring-aop,aspectjweaver,aopalliance,spring-aspects,cglib
这里面用到了Aspectj,这是对面向切面编程的框架使用注解实现
编写切面类,加入注解@Component(ioc注入),@Aspect(标记为切面类)@Order(值越小优先级越高)(切面优先级)
所有的通知注解中需加入(value="切入点表达式,execution(访问修饰符和返回值 全限定类名.方法.(参数)),其中的参数可以用*代表所有"),
方法上注入@Before代表前置通知,
@After后置通知 作用于方法的finally语句块
@AfterReturning返回通知 在注解中可以加入returning=“result”参数,相当于接收到了原来方法的返回值,然后就可以在方法中加入Object “result”参数获得刚才得到的返回值,作用于方法执行之后
@AfterThrowing异常通知,在注解中可以加入 throwing=“ex” ,方法中可以加入Exeption ex 获取异常的信息,也可以在方法中放入相应的异常实现指定异常处理
@Around环绕通知 方法中需加入ProceedingJoinPoint参数 proceed()方法相当于执行方法,进行try,catch相当于动态代理模式的实现在里面添加前置后置,异常返回通知
如果有公共的切入点就可以在一个方法上定义@Pointcut加入之前注解中value需加入的值,然后其他的通知注解中的value直接放这个方法名就行。
方法中可以写JoinPoint joinPoint参数 joinPoint.getArgs()获取方法参数.getSignature().geName()获取方法名
xml加入:<aop:aspectj-autoproxy />表示启用切面
基于xml的AOP实现
<aop:config> <aop:aspect id="" order="" ref="切面bean的引用,引用其名字"> <aop:before method="对应的方法" pointcut="切入点表达式"></aop:before> <aop:after method="" pointcut=""></aop:after> <aop:after-returning method="" pointcut=""></aop:after-returning> <aop:after-throwing method="" pointcut=""></aop:after-throwing> </aop:aspect> </aop:config>
<aop:config> <aop:aspect> <aop:pointcut id="" expression=""/> <aop:before method="" pointcut-ref="引用"></aop:before> </aop:aspect> </aop:config>
JdbcTemplate
引入配置文件 <context:property-placeholder location="db.properties"></context:property-placeholder> 创建数据源 <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driver}"></property> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> 通过数据源配置jdbctemplate <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean>
JdbcTemplate中封装jdbc的操作
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
@Transactional 开启事务注解
可以加到方法上或者类上
其中可以设置的属性
propagatino:事物的传播级别/行为,A和B方法都有事务,在A调用B时,会将A中的事务传播给B方法,B方法对于事务的处理方式就是事务的传播行为
Propagation.REQUIRED:必须使用调用者的事务
Propagation.REQUIRES_NEW:不是用调用者的事务,使用新的事务进行处理
Propagation.SUPPORTS:A中有事务则用没有事务则不用事务
Propagation.NOT_SUPPORTED:当前方法不运行在事务中
Propagation.MANDATORY:当前方法必须运行在事务内,否则直接抛出异常
Propagation.NEVER:当前方法不应该运行在事务中,如果有事务则抛出异常
Propagation.NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
isolation:事务的隔离级别,在并发的情况下,操作数据的一种规定
读未提交:脏读,可能会读到会回滚的无意义的数据
读已提交:不可重复读
可重复读:幻读,正在读时的数据不允许更新和操作
串行化:相当于单线程,一次只能处理一件事情,性能较低,消耗较大
timeout:在事务强制回滚前最多可以执行(等待)多长时间
readyonly:指定当前事务中的系列操作是否为只读,默认为false如果是只读作用提醒mysql不需要加锁
rollbackfor|rollbackforclassname|norollbackfor|norollbackforclassname:因为什么异常或者不因为什么异常而回滚
xml事务管理
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <aop:config> <aop:pointcut id="pointcut" expression="切入点表达式"/> <aop:advisor advice-ref="tx" pointcut-ref="pointcut"/> </aop:config> <tx:advice id="tx" transaction-manager="dataSourceTransactionManager"> <tx:attributes> <tx:method name=""/> 可以使用通配符 </tx:attributes> </tx:advice>