Spring入门(二)— IOC注解、Spring测试、AOP入门
2018-02-19 21:59
399 查看
一、Spring整合Servlet背后的细节
1.为什么要在web.xml中配置listener
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
配置listener主要是为了捕获项目发布|服务器启动的契机,为了解析xml,创建工厂。这个listener是spring官方提供的,里面已经具备了解析xml和创建工厂的代码。
2.为什么要在web.xml中配置context-param
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param>
正如上面所说的,listener捕获到了项目发布的契机,进而去创建工厂。但是创建工厂需要解析xml。spring的这个监听器里面,默认会到WEB-INF/applicationContext.xml.如果不想放置到这个位置,可以通过一个context-param来告诉spring,我们的配置文件在哪里。
classpath表示这个文件是位于类路径底下。classes目录
3.为什么使用工具类也能拿到工厂,到底工厂放在了哪里?
publicclassContextLoaderListenerextendsContextLoaderimplementsServletContextListener{ //项目一发布,就执行 publicvoidcontextInitialized(ServletContextEventevent){ //创建工厂 initWebApplicationContext(event.getServletContext()); } } publicWebApplicationContextinitWebApplicationContext(ServletContextservletContext){ ... if(this.context==null){ //创建工厂 this.context=createWebApplicationContext(servletContext); } //把创建好的工厂,存储到作用域 //servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); ... } //spring为了简化程序员获取工厂的工作,就提供了一个工具类,其实这个工具类就是对取值的代码进行封装 ApplicationContextcontext=WebApplicationContextUtils.getWebApplicationContext(getServletContext()); //ApplicationContextcontext=(ApplicationContext)getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
二、IOC注解
1.注解入门
导入jar包spring-aop-xxx.jar
导入约束
<beansxmlns="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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
在xml里面打开注解扫描开关
<!--告诉spring要去解析类,因为类上有注解--> <context:component-scanbase-package="com.pri.service.impl"/>
在托管的类上打注解
@Component("us") publicclassUserServiceImplimplementsUserService{ ... }
问工厂要实例对象
//创建工厂创建工厂,需要解析xml,所以要传递进去xml文件 ApplicationContextcontext=newClassPathXmlApplicationContext("applicationContext.xml"); //问工厂要实例对象 UserServiceuserService=(UserService)context.getBean("us"); //调用方法 userService.save(); //关闭工厂:以后我们几乎不会关闭工厂。 ((AbstractApplicationContext)context).close();
2.注解创建对象
/* 1.@Component组件,表示要托管这个类,让spring创建这个类的实例。括号里面的us其实就是id标识符 2.@Component是通用的注解,对任何托管的类都可以使用,但是spring为了迎合三层架构,所以对每一层 也给出了具体的注解。 Action---@Controller Service---@Service Dao---@Repository:仓库, 建议:如果以后托管三层中的类,请使用具体对应的注解,如果托管的是普通的其他类。@Component 3.默认生成的实例还是单例,如果想做成多例,那么还得添加一个注解 @Scope("prototype") 4.@PostConstruct//初始化实例的时候调用 @PreDestroy//销毁实例之前,调用 5.如果使用注解托管某一个类,不写属性值,那么默认的id标识符就是类的名字(首字母是小写)userServiceImpl 6.<!--如果想要扫描多个包,就写一个通用的前缀即可--> <context:component-scanbase-package="com.pri"/> */
3.DI注解开发(注入对象)
使用注解来完成依赖注入。一般注解注入,它针对的点是对象的注入。spring针对对象的注入,提供了两个注解
@Resource和
@Autowired
常用的注解就两个@Resource&@Autowired
@Resource(name="ud")根据给定的标记找到对应的类,创建对象,注入进来。
@Autowired自动装配,会找到对应的实现类创建对象,注入进来。但是如果存在多个实现,那么会抛出异常
@Repository("ud") publicclassUserDaoImplimplementsUserDao{ } publicclassUserServiceImplimplementsUserService{ @Resource(name="ud")//spring拿着ud找到具体的类,然后创建实例,注入进来。 privateUserDaouserDao; ... } ---------------------------------------------------------- publicclassUserServiceImplimplementsUserService{ @Autowired//自动装配根据注入的接口类型找到对应的实现类,注入进来。 privateUserDaouserDao; ... }
4.xml和注解混合使用
在项目里面,使用xml和注解来完成Spring的配置。
xml:负责完成IOC(对象的创建)
注解:负责完成DI(属性的注入)
xml托管类
<context:component-scanbase-package="com.pri"/> <beanid="ud"class="com.pri.dao.impl.UserDaoImpl"></bean> <beanid="us"class="com.pri.service.impl.UserServiceImpl"></bean>
注解完成注入:
publicclassUserServiceImplimplementsUserService{ @Resource(name="ud") privateUserDaouserDao; }
三、Spring测试
导入jar包spring-test-xxx.jar
托管业务逻辑类,不管是用xml还是注解都可以
<beanid="us"class="com.pri.service.impl.UserServiceImpl"></bean>
在测试类上打上注解,给测试类的成员变量注入值
//spring扩展了junit的运行环境,除了有测试功能之外,还在里面定义了创建工厂的代码 @RunWith(SpringJUnit4ClassRunner.class) //告诉spring的测试环境,配置文件在哪里 @ContextConfiguration("classpath:applicationContext.xml") publicclassTestUserService{ //测试类里面出现的注解,不用打开扫描开关。因为这个测试环境里面,它会解析这个测试类的注解。 @Autowired privateUserServiceuserService; @Test publicvoidtestSave(){ userService.save(); } }
四、AOP
1.什么是AOP,它有什么用?
AOP(AspectOrientedProgramming,面向切面编程),可以说是OOP(ObjectOrientedPrograming,面向对象编程)的补充和完善。OOP更多的是侧重于上下间的关系(继承关系、实现关系),OOP很难体现左右间的关系。核心:在不改动源码的前提下,对原有功能能完成扩展|升级
2.AOP的底层原理
aop不改源码,但是能够扩展和升级代码。能够做成这个事情,只有三种解决手法:
装饰者模式,
静态代理、
动态代理。AOP选择的是动态代理,装饰者模式和静态代理,要求我们必须写出来装饰类和代理类。动态代理的实现机制,有两种:
基于JDK的动态搭理、
基于Cglib的动态代理