Spring框架
Spring框架(全栈轻量级开源框架,IOC inverse of control 反转控制和AOP aspect oriented programming面向切片编程)。2017年9月发布5.0通用版。
Spring框架基于XML的IOC配置。Bean是可重用组件,JavaBean范围大于实体类,创建service和dao对象。创建properties配置文件,其中设定dao和service,使用BeanFactory读取。
BeanFactory中使用静态代码块为service和dao创建对象(反射技术)。多例对象(支持多线程但是反复创建效率低),单例对象(只创建一次,效率高)。
IOC
由BeanFactory决定创建对象方式(翻转控制),削减程序间的耦合。Spring创建对象的方式,读取xml文件,由代码创建对象。idea可以查看类的继承关系。其中,ApplicationContext适用单例对象,BeanFactory适用多例对象。常用的为单例对象。
创建Bean对象的三种方式:使用xml文件指定id和class等,调用该xml文件创建对象。基本由bean.xml中的bean标签指定,默认创建单例对象,scope范围为:singleton属性单例,prototype多例,request请求范围,session会话范围,global-session集群环境会话范围(负载均衡的多物理机虚拟化一个session)。
单例对象中:bean标签的init-method选定初始化方法,destory-method选定销毁方法,其生命周期和容器相同。多例对象中,使用对象才开始生命周期,使用java的垃圾回收器自动回收。
依赖注入(Dependency Injection),IOC降低了程序的耦合。能注入的数据类型方法使用构造函数,set方法,或注解。
构造函数注入:在bean标签内部,使用constructor-arg标签,定义type数据类型属性,index指定索引赋值参数,name指定参数名称,value放入值(传入的值为对象则使用bean标签创建,使用ref属性传入数据替代value)。
set方法注入:在bean标签内部,使用property标签,使用name(不区分大小写)指定传入位置,value和ref传入数据。传入集合类型的数据,在property标签内部定义array标签,定义value标签,中间为值。或map标签,entry标签指定key value属性。props标签prop标签,指定key属性和中间值等。
常用实现类
创建Bean的三种方式
基于注解的IOC
Spring基于注解的IOC(代替bean.xml文件)。在service层的实现类中,写入注解用于创建对象,注入数据,改变作用范围,定义声明周期的init和destory。需要修改bean.xml为:图
@Component将当前类传入Spring容器中。@Controller用在表现层,@Service用在业务层,@Repository用在持久层,和@Component功能基本完全相同,传入的参数为产生的对象名。
@Autowired自动按照类型注入,匹配则注入成功(类和方法上使用)。有多个匹配成功则比较名称相同则匹配到相同名的实现,没有则报错。@Qualifier用于指定注入的dao实现对象名注入,也可作为参数指定独立使用,@Resource指定bean的id进行注入。
@Value注解用于注入基本类型和String类型的数据(可以使用spring的EL表达式,写法如:${})。
@Scope注解用于改变作用范围,@PreDestory用于指定销毁方法,@PostConstruct指定初始化方法。
配置类
SpringConfiguration.java配置类,@Configuration注解表示该类为配置类,@ComponentScan注解用于指定创建容器扫描的包(value和basePackage都可)。@AliasFor别名
@Bean用于将当前方法返回值作为Bean对象存入IOC容器中,name指定bean的id(默认为当前方法名)。当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。查找的方式和Autowired注解的作用是一样的。
当@Configuration注解只加载AnnotationConfigApplicationContext字节码则可省略,但是需要对其中的注解扫描则必须存在。@Import用于导入其他配置类,引入层次关系。
@PropertySource用于指定properties配置文件,传入classpath:类路径。
junit集成了main方法,判断@Test等注解进行执行(不考虑spring框架,则没有自动数据注入等,导入spring-test并配置解决),使用@Runwith为测试类进行junit4.1.2以上的spring配置,传入SpringJUnit4ClassRunner.class。@ContextConfiguration指定配置(class注解位置或Location的xml文件)。
AOP
使得方法中获取的对象为同一个,以确定如数据库事务等能够回滚事务,需要使用ThreadLocal对象绑定线程,使用自定义的dao和service实现然后调用,或使用代理的方式创建service调用实现。
动态代理不修改源码的方法对方法进行增强,Proxy.newProxyInstance()中传入被代理对象的类加载器,字节码数组接口,代理方法InvocationHandler。重写invoke方法,其中添加新功能和写入method.invoke传入原方法(基于接口)。
cglib基于子类的动态代理(第三方提供,基于子类),使用Enhancer.create方法传入Class字节码和回调函数new MethodInterceptor并写入内容。
AOP,在运行期不修改代码对方法增强(使用动态代理),将重复代码抽取,提高可重用性。连接点(所有方法),切入点(被增强的方法),通知(拦截后的事务,前置,后置,异常,最终,环绕[整个事务])。Proxy代理对象,Aspect切入点和通知的结合。切面:切入点和通知之间的关系。
在bean.xml中添加aop的支持,导入service对象,配置aop。使用aop:config标签,写入aop:aspect标签,定义id和ref属性类,在其中写入aop:before表示前置通知的方法(方法执行前执行,after-throwing异常通知,after-returning后置通知,after最终通知),其中pointcut属性为切入点表达式(execution被增强的方法)。
切入点表达式:访问修饰符可以省略,返回值可以使用*表示任意返回值,包名可以使用通配符表示任意包。类名和方法名都可以使用通配符。由aspectj解析表达式。aop:printcut标签可以配置切入点表达式,写id用于引用,配置该标签应该放置在引用前。
当配置环绕通知,切入点方法ProceedingJoinPoint接口的proceed方法切入点方法,提供实现类如getArgs方法供使用,使用代码控制前置后置异常最终通知。
修改xml文件依赖后,开启支持(aop:aspectj-autoproxy)Deng ,可以使用注解方式进行aop配置(调用顺序有问题)。@Aspect表示当前类是一个切面。@Around定义环绕通知,@Before,@After,@After-Returning,@After-Throwing,传入引用方法。@EnableAspectJAutoProxy不使用xml的配置。
JDBCTemplate
JDBCTemplate(spring的类对jdbc封装),其中的query方法查询(选定方法,传入sql,RowMapper,查询参数,queryForObject查询返回一行一列),update方法保存删除更新。
使用xml进行ioc配置。jdbcDaoSupport包使用xml配置,不支持注解配置ioc。
aop实现事务控制:配置xml中的aop:config等,见图。或者使用注解进行配置(通知后置通知顺序问题,需要使用环绕通知,控制通知执行的顺序)。
事务控制的API,定义隔离级别,传播行为,超时时间,只读事务。存储点(事务按步提交)等。
bean.xml中配置事务管理器,配置事务通知tx:advice标签(tx:attributes标签中,配置tx:method等,见图),配置切入点表达式。
xml中修改后可以使用注解配置事务控制(事务管理器,开启spring对注解事务的支持,使用tx:annotation-driver,在需要事务的地方使用@Transactional注解并传入参数)。也可以进行纯注解进行事务控制。
也可以进行编程式的事务控制(不常用)。见代码day04_eesy08account_tx。
JDK8在创建对象和赋值等方面更快,响应式编程风格,junit5等。