1.2.spring

(一)spring初识

1.spring的用途

spring是一个对象容器(BeanContainer),spring框架中管理对象(控制层对象,服务层对象,mapper代理对象,非三层对象)。

IOC(控制反转):原来我们自己new,用了spring后,由spring来通过反射创建对象,并保存对象在BeanFactory对象中。

2.为什么要把对象注册到spring容器中

  • 解耦:把控制层,服务层,持久层进行解耦,每层都依赖下层的抽象接口;

经典MVC架构目的就是为了层与层之间解耦,达到下层变动上层不变,但如果没有第三方容器存在的话,仍然需要开发者自身来在上层把依赖的下层对象实例化。

把UserServlet,UserServiceImpl,UserDaoImpl,DruidDataSource都放在容器中,由spring来为这些bean对象中依赖的变量去注入值(根据变量名或变量类型去容器中查找对应的bean)

  • aop:面向切面编程。

    spring容器管理bean对象,spring拿着对象的引用,就能够在运行期间通过动态代理模式,来统一的对某些对象进行扩展完善。

3.入门spring

步骤:

1.加spring的依赖jar包
2.向spring中注册bean,注册bean的方法很多
3.从spring中获取bean
  • 1.加spring包

    spring的四个核心包,缺一不可:beans,context,core,expression

    一个apache的commons-logging.

  • 2.向spring中注册bean

    创建spriing.xml文件,通过bean标签注册bean。

    <bean id="userService" class="com.javasm.sys.service.SysuserServiceImpl"></bean>3.从spring中获取bean
    
  • 3.从spring中获取bean

    1.加载spring.xml,创建spring的容器对象ApplicationContext
     ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
     
    2.从spring中获取bean
    ISysuserService userService1 = (ISysuserService) ac.getBean("userService");
    ISysuserService userService =ac.getBean(ISysuserService.class);
    
    3.注意点:
    bean对象什么时候创建:容器初始化时;
    bean对象创建几次:一次,对象默认是单例的。
    bean类中必须有无参构造:因为spring内部通过反射调用无参构造实例化对象
    

4.了解下spring容器接口的结构

BeanFactory

​ ApplicationContext

​ ClasspathXMLApplicationContext:加载类路径下的xml文件初始化容器

​ FilePathXmlApplicationContext:加载文件路径下的xml文件初始化容器

​ AnnotataionConfigApplicaitonContext:加载类文件初始化容器

编码设计原则:

单一原则:

开闭原则:代码对于添加是开放的;对于修改是封闭的。

(二)spring 理解

1.作用

1.1 spring是一个第三方的bean容器框架,也称为ioc容器。

1.2 当spring拿到对象的引用后,即可以通过动态代理模式,为bean对象的方法进行扩展改进(统一加入事务控制,统一加入日志组件,统一进行异常处理)。

2.使用

2.1 加入spring的4个核心包。1个commons-loggings日志接口包

2.2 创建spring的配置文件,配置文件用来注册bean(控制层bean,服务层,持久层,管理器对象)

2.3 实例化容器对象ApplicationContext–>ClasspathXmlApplicationContext,容器对象应该是全局唯一的对象。

2.4 使用容器对象,获取bean,

2.4.1 按照名称获取
	getBean("bean的id")
2.4.2 按照类型获取
	getBean(Class clz)

3.概念

3.1 ioc:控制反转

对象的管理由应用自身维护,交给独立第三方的容器来管理对象(创建,状态,销毁,对象之间的依赖关系)

  • 3.1.1 注册bean方法1:bean标签

主要用在无源码的类上。比如DruidDataSource,jar包里的类要注册容器

<bean id="userController" class="com.javasm.sys.controller.SysuserController"  lazy-init="true" init-method="initData" destroy-method="closeData" scope="prototype|singleton"></bean>
注意点:
-bean对象默认是在容器初始化时实例化的,可以通过lazy-init指定延迟初始化bean。
-class不能写接口名。
-id不能同名。
-spring本身是可以存储同类型的对象,在获取bean的时候注意获取按照类型获取bean,不能按照接口类型。
-对于特殊的bean对象(DruidDataSource),可以通过init-method或destroy-method指定初始化与释放资源。
-spring管理的bena对象默认是单例状态,可以通过scope="prototype"修改对象的单例为原型模式,每次getBean得到的是一个新对象。
  • 3.1.2 注册bean方法2:静态工厂

主要用在复杂对象的注册

工厂类:是一种设计模式,用来创建对象使用。

针对复杂对象的构建,需要用到工厂实例化bean,比如SqlSessionFactory,无法直接new
 <bean id="factoryBean" class="com.javasm.factory.MySqlSessionFactoryBean" factory-method="类中的静态方法名"></bean>
  • 3.1.3 注册bean方法3:实例工厂

主要用在复杂对象的注册

<!--先实例化工厂对象-->
<bean id="factoryBean" class="com.javasm.factory.MySqlSessionFactoryBean"></bean>
<!--再调用实例工厂对象的方法,把方法的返回值注册到容器中-->
<bean id="sqlSessionFactory" factory-bean="factoryBean" factory-method="createSqlSessionFactory"></bean>
  • 3.1.4 注册bean方法4:包扫描

主要用在自己编写的类上。

<!--在类上加注解:@Controller,@Service,@Repository,@Component-->
<context:component-scan base-package="com.javasm"></context:component-scan>
    
注意点:
-包扫描需要加入spring-aop.jar。
-bean的id默认是类名首字母小写,可以指定注解的value属性自定义id名。
-这四个注解原则上是分别注解控制层,服务层,持久层,非三层的类;本质上四个注解效果一样。学到springMVC控制层框架,这个框架的Controller独立识别。

3.2 DI:依赖注入

  • 3.2.1 依赖注入方法1:set注入
<bean id="userController" class="com.javasm.sys.controller.SysuserController">
     <property name="属性名" ref="bean的id名"></property>
</bean>
注意点:
-类中要注入值的属性必须有set方法
-如果要注入的值是容器中的一个bean对象的话,使用ref属性,ref=“bean的id”
-如果要注入的值是一个简单类型(String,包装类,基本类型,Date)的话,使用value属性,value=“值”
  • 3.2.2 依赖注入方法2:构造器注入
<bean id="userController" class="com.javasm.sys.controller.SysuserController">
        <constructor-arg name="sysuserService" ref="userService"></constructor-arg>
        <constructor-arg name="str" value="张三"></constructor-arg>
    </bean>
注意点:
-index与name属性二选一
-ref与value属性二选一
  • 3.2.3 依赖注入方法3:集合属性注入
为bean对象中的List,数组,set,Map属性赋值
property的list,array,set,map子标签
  • 3.2.5 依赖注入方法5:自动装配
与包扫描进行bean注册一起使用
<!--在类上加注解:@Controller,@Service,@Repository,@Component-->
<!--在属性上加注解:@Autowired,@Resource-->
<context:component-scan base-package="com.javasm"></context:component-scan>

//Autowired:先按照类型找,如果按照类型无法确定bean对象;再按照变量名去找。
//Resource:先按照变量名找,找不到再按照类型找。建议使用。

总结ioc与di:

通常情况下自己编写的类使用包扫描注册bean(@Controller,@Service,@Repository,@Component),使用自动装配来维护bean的依赖关系(@Autowired,@Resource)。

通常情况下jar包中类使用bean标签注册对象(),使用properties标签来维护bean的依赖关系

4.spring与junit整合

//1.加入spring-test.jar
//2.在测试类上加runwith,ContextConfiguration两个注解,初始化容器,并把测试类也注册到容器
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:componentScan.xml")
public class Test4_junit{
    
    @Resource
    private GoodsController gc;
    
    @Test
    public void ddd(){
        gc.xxxx();
    }
}

5.了解xml文件解析

服务端进行xml解析,使用dom4j;在移动端进行xml解析,使用pull;

//1.加入dom4j.jar
//2.关于dom4j组件的的类,重点记忆一个类SAXReader
 SAXReader reader = new SAXReader();
 Document doc = reader.read(InputStream in);

properties文件解析

Properties p = new Properties()
p.load(InputStream in)

6.其它常用标签

1.import标签,导入其它spring风格的xml文件
<import resource="classpath:factory.xml"></import>

2.context:property-placeholder标签,导入类路径下的properties文件到spring容器
<context:property-placeholder location="classpath:jdbc.properties" ignore-unresolvable="true"></context:property-placeholder>

常见异常:

1.在按照类型获取bean的时候,指定类型有多个bean对象存在。
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.javasm.sys.service.ISysuserService' available: expected single matching bean but found 2: userService,userService2

2.容器创建失败,会告诉哪个bean创建异常,一般都是bean中属性注入出问题,或者没有无参构造
 org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'goodsController': Unsatisfied dependency expressed through field 'sysuserService'; 
 
 3.加载jdbc.properties文件时,文件中的key不能单个单词,获取不到
 
 4.当加载多个properties文件时,Could not resolve placeholder 'jdbc.url' in value "${jdbc.url}"

注意点:

架构层面的对象(mvcdao)交给spring,业务层对象(数据库表对应的实体类)是不交给spring

(三)spring 须知

1.通过类配置bean

在ssm框架中,使用xml配置的方式;在springboot框架中,推荐使用类配置方式。

1.添加spring的核心包(4个core,1个日志,1个aop,1个test)
2.创建一个类配置文件,类上加@Configuration
3.加载类配置文件初始化容器,new AnnotationConfigApplicationContext(Class clz)

在类配置文件中注册bean:

  • 包扫描
@Configuration
@ComponentScan("com.javasm")//6个注解
public class ContextConfig {

}
  • bean注解
 @Bean(initMethod = "init",destroyMethod = "close")
    public DataSource initDruid(){
        DruidDataSource ds = new DruidDataSource();
        ds.setUrl("jdbc:mysql://127.0.0.1:3306/704b");
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUsername("root");
        ds.setPassword("root");
        ds.setInitialSize(2);
        return ds;
    }

bean对象状态修改:

  • 单例改原型
//bean对象id默认是类名首字母小写
@Controller
@Scope("prototype")
public class SysuserController {
}

//bean对象的id默认是方法名
@Bean(initMethod = "init",destroyMethod = "close")
    @Scope("prototype")
public DataSource initDruid(){
        DruidDataSource ds = new DruidDataSource();
        ds.setUrl("jdbc:mysql://127.0.0.1:3306/704b");
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUsername("root");
        ds.setPassword("root");
        ds.setInitialSize(2);
        return ds;
  • 指定初始化与销毁方法
自定义的类:
@PostConstruct
    public void init(){
        System.out.println("初始化方法");
    }

@PreDestroy
    public void close(){
        System.out.println("销毁方法");
    }

bean标签注册的类:
@Bean(initMethod = "init",destroyMethod = "close") @Scope("prototype")
  • 包含其他配置类:
@Import(DaoConfig.class)
  • 加载properties文件
@PropertySource(value="classpath:jdbc.properties",ignoreResourceNotFound = true)
  • 通过bean注解注册的bean注入依赖对象
 @Bean
    public SysuserController createUserController(ISysuserService sysuserService){
        SysuserController sysuserController = new SysuserController();
        sysuserController.setSysuserService(sysuserService);
        return sysuserController;
    }

总结:

@Configuration   声明一个类是配置类
@ComponentScan   开启包扫描注解(6个核心,import,ProeprtySource,PostConstruct,PreDestroy...@PropertySource  加载外部资源文件
@Import          导入其它配置类
@Bean            注册bean对象到容器
@Scope           指定bean的单例原型状态
@PostConstruct   指定bean对象的初始化方法
@PreDestroy      指定bean对象的销毁方法

2.aop概念

aop:是面向切面对象编程,是对oop面向对象编程的一种补充。

在项目编写之初,oop把核心业务进行实现,比如付款业务。在核心业务完成以后,又提出要添加辅助性的功能,比如在付款业务中加入日志记录,记录每个付款接口的执行时间。把这些辅助型的业务对象称为切面。

切面aspect:即提取出来的辅助业务对象(日志,执行事件,事务),TimeInfo对象

通知advice:即切面类中的方法(前置通知,返回通知,异常通知,最终通知,环绕通知)。begin和end方法

织入weave:在程序运行期间,通过动态代理模式,把一个切面对象中的某个方法作为通知 插入 到某个目标对象的某个连接点方法中。

连接点joinpoint:即目标对象中的需要被扩展的业务方法。pay方法

目标对象target:即被代理的原生对象。WechatPay对象

切入点pointcut:通过一个表达式来描述出来连接点的集合.

3.spring的aop使用

spring对aop进行了实现,基于ioc容器,spring持有了对象的引用,在对象上加代理对象,把切面中的通知方法织入到原对象中。

3.0 环境准备

1.添加6个aop需要使用的jar包
spring-aop;
spring-aspect;
cglib:动态代理模式第三方组件包,与Proxy类职责是一样的,但比Proxy更强大。Proxy方法创建代理类要求被代理对象必须有接口。cglib支持被代理对象没有上级接口。
aspectj组件3个jar包:这个组件是一个aop组件包,spring借用了该注解定义的注解。

3.1基于注解的aop实现

1.在xml文件中开启aop注解的识别
 <!--用来识别aop相关的注解:@Aspect,@Pointcut,@Before,@After,@AfterReturning,@AfterThrowsing,@Around-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

@Aspect:定义到切面类上,表示当前类是一个切面对象
@Before:定义到切面类的方法上,表示该方法是一个前置通知方法。
@AfterReturning:定义到切面类的方法上,表示该方法是一个返回通知方法.
@AfterThrowing:定义到切面类的方法上,表示该方法是一个异常通知方法
@After:定义到切面类的方法上,表示该方法是一个最终通知方法
@Around:定义到切面类的方法上,表示该方法是一个环绕通知方法,经典玩法就是事务切面

2.定义一个切面类:
@Component
@Aspect
public class 类名(){}

3.在切面类定义切入点表达式:
	方法1:通过execution(返回值 方法名(形参列表))
		@Pointcut("execution()")
		public void dd(){}
	方法2:通过@annotation(注解名)
		@Pointcut("@annotation(注解的全名)")
		public void dd(){}

4.在切面类中定义通知方法
	@Before,@After,@AfterReturning,@AfterThrowsing,@Around
	在所有通知方法中都通过添加JoinPoint形参来获取连接点信息。
	在返回通知中可以获取连接点方法返回值
	在异常通知中可以获取连接点方法产生的异常

3.2基于xml配置的aop实现

 <!--注册bean到spring容器-->
  <bean id="logAspect" class="com.javasm.sys.aspect.LogAspect"></bean>
    
    <!--进行aop的配置-->
    <aop:config>
        <aop:aspect ref="logAspect">
            <aop:pointcut id="servicePointcut" expression="execution(* com.javasm.*.service.*.*(..))"></aop:pointcut>
            <!--<aop:around method="aroundMethod" pointcut-ref="servicePointcut"></aop:around>-->
            <!--<aop:after-returning method="afterReturning" pointcut-ref="servicePointcut" returning="obj"></aop:after-returning>-->
        </aop:aspect>
    </aop:config>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值