Spring快速入门的笔记

Spring

SSM

S:Spring:核心思想管理IOC组件,使用AOP思想完成功能增强
S:SpringMVC:接收浏览器发送的请求,并响应浏览器数据
M:Mybatis:封装JDBC,负责访问数据库,完成持久化对象
SSM:将各个框架整合,进一步了解各个功能的框架

IoC 控制反转

IoC容器负责管理大量对象的创建以及初始化(一般是service与dao),在IoC中,被管理的对象统一被称为Bean。在这个过程中,通过配置告知IoC容器,通过接口获取到IoC容器,获取到IoC容器后,通过接口方法获取bean对象,在pom.xml倒入坐标。
以小demo为例:

     |--dao
     ---impl--BookDaoimpl
     ---BookDao
     |--service
     ---impl--Bookserviceimpl
     ---Bookservice

操作步骤:
1.导入Spring坐标Spring-context(在pom.xml文件中写入依赖)
2.在项目文件夹内,右键-> New-> XML Configuration File-> Spring Config并给该文件起名字“applicationContext.xml”
3.进入applicationContext.xml”,配置bean,代码如下:

<beans>
<bean id ="bookdao" class="Demo.dao.impl.BookDaoimpl"/>

<bean id ="bookservice" class="Demo.service.impl.Bookserviceimpl"/>
</beans>

tips: bean标签化,ID是起名字(不固定),class为要实例化的对象类

4.获取IoC容器,新建一个Java主程序,代码如下:

public static void main(String[] args){
    ApplicationContext ctx = new ClassPathApplicationContext("application.xml");
    BookDao = (BookDao)ctx.getBean("bookDao");//这里引用的是ID
}

通过实例:通过在applicationContext中注册bean以及对象的bean信息即可,通过获取配置类的ID获取对象。

DI 依赖注入

在容器中bean与bean建立依赖关系的整个过程

操作实现:
1.去掉业务中new 对象的部分,仅保留声明的对象部分:(private BookDao bookdao,后面new部分不写)

2.提供对应的setter方法,传递参数使之能够传递到当前对象的方法

3.进入applicationContext.xml”中,在对应的BookDao 的内部标签中配置service与dao的关系:

<bean id ="bookdao" class="Demo.dao.impl.BookDaoimpl"/>

<bean id ="bookservice" class="Demo.service.impl.Bookserviceimpl">
<property name="bookDao" ref="bookdao"/>
</>

这里在自己的类中不去引用其他类的对象,property的配置就不需要写。

tips: property标签化,name表示关联的Java类文件中的对象属性名称(bookdao),ref属性代表参照的是配置文件中的哪一个bean的ID或者name(下节说到)

bean基础配置

可以为对象指定别名,在bean中使用name属性:

<bean id ="bookdao" name="dao dao2 " class="Demo.dao.impl.BookDaoimpl"/>

tips:使用多个别名用空格隔开

可以创建多个对象,在bean中使用scope属性,默认创建单例singleton,创建多个使用prototype

<bean id ="bookdao" name="dao dao2" scope="prototype" class="Demo.dao.impl.BookDaoimpl"/>

bean实例化

1.bean实例化–构造方法,在类中提供一个可以访问的无参构造方法,会调用
bean常规配置:

<bean id ="bookdao" class="Demo.dao.impl.BookDaoimpl"/>

2.bean实例化–静态工厂(这种方式为了兼容早期项目,装饰修改)
在原有项目的基础上,新建了类,里面有静态方法,用于返回创建的对象

public class BookDaoFActory {
    public static Bookdao getBookDao(){
        return new BookDaoimpl();
    }
}

配置:

<bean id ="bookdao" 
factory-method:"getBookDao"
class="Demo.dao.factory.BookDaoFactory"/>

tips:class所指定的类为创建对象,但是为了指定需要返回的方法对象类型,需要指定类里的方法指定返回的对象类型。
3.实例工厂与factory Bean
对象的的方法并非静态方法,而是实例方法,
配置:

<bean id ="userFectory" 
class="Demo.dao.factory.userBookDaoFactory"/>

<bean id ="userDao" 
factory-method="getUserDao" factory-bean="userFactory"/>

tips: 这里更为麻烦了一些,相当于对原来的bean进行了拆解。

工厂方法在原有的接口与实现方法上,又出来一个新的类–工厂类。用于返回对象

4.factoryBean实例化:*
新建一个userDaoFactoryBean类,并实现FactoryBean接口,泛型类型为自己想创建的对象返回类型,并实现这个接口的方法。

生命周期

1.在配置bean属性中有init-method属性,destroy-method属性,值分别为init,destroy

2.当然在java文件中使用接口也可以控制,继承initializingBean,DisposableBean

3.关闭容器的操作
ConfigurableApplicationContext
close()
registerShutDownHook()

依赖注入

setter注入:
简单类型(基本数据类型,string等)
引用类型(引用的对象)
构造器注入:
简单类型
引用类型

setter在之前已经说过,即:
在Java类中定义引用类型属性(private),并提供可以访问的set方法,然后在bean的property标签的ref属性注入引用的类型对象(在set的对象)
tips;其中文件中property的标签不是随便写的,一定要写在定义且设置set的配置bean中。

简单类型引用和引用一样,首先定义int或者String类型的数据,然后设置set方法引用,然后在该类文件的配置文件bean中进行property属性的定义,使用属性name绑定引用对象,然后使用value属性动态绑定对于属性的值。

构造器注入:*
首先,去掉set方法,换成传递参数的构造方法,然后在配置文件中的bean配置,

<bean id ="bookdao" class="Demo.dao.impl.BookDaoimpl"/>

<bean id ="bookservice" class="Demo.service.impl.Bookserviceimpl">
<constructor name="bookDao" ref="bookdao"/>
</bean>

tips:其中,配置构造器中的name是构造方法的形参。

为了解决简单引入注入问题中因为类中变量名称变化,而在配置中绑定失败的问题,在配置中,可以通过定向传递类型,与绑定索引位置方法进行参数绑定传递:

<bean id ="bookdao" class="Demo.dao.impl.BookDaoimpl"/>

<bean id ="bookservice" class="Demo.service.impl.Bookserviceimpl">
<constructor type=“java.lang.String” value="100"/>
</bean>

吐过构造参数中存在两个形参,第一个为String,第二个为int:

<bean id ="bookdao" class="Demo.dao.impl.BookDaoimpl"/>

<bean id ="bookservice" class="Demo.service.impl.Bookserviceimpl">
<constructor index="0" value="SSM"/>
<constructor index="1" value="100"/>
</bean>

bean依赖自动装配

Java中类文件保留set方法,即形参引用,在配置文件对对应的bean中自动参数进行配置即可:

<bean id ="bookdao" class="Demo.dao.impl.BookDaoimpl"/>

<bean id ="bookservice" class="Demo.service.impl.Bookserviceimpl" autowire="byName/byType"/>

tips:自动装配有几点需要注意:装配只用在引用类型中,并不能使用在简单类型中。第二个装配中,保证类型唯一,推荐使用ByType,而指定了名称,则使用ByName(不推荐),自动装配优先级低于set与构造器注入,同时存在则自动装配失效。

集合注入

简单类型的集合注入array,list,map,set,prosperty
在类中进行定义并存在set 方法:

private int[] array;
private Lsit<String> list;
private Set<String> set;
private Map<String, String> map;
private Prosperties pros;

public void setarray(int[] array){
    this.array = array
} ...

在配置中需要这样进行分别配置:

<bean id ="bookdao" class="Demo.dao.impl.BookDaoimpl">
   <property name="array">
       <array>
           <value> 100</value>
           <value> 200</value>
           <value> 300</value>
       </array>
   </property>
   <property name="list">
       <list>
           <value> 100</value>
           <value> 200</value>
           <value> 300</value>
       </list>
   </property>
   <property name="set">
       <set>
           <value> sre</value>
           <value> str1</value>
           <value> sav</value>
       </set>
   </property>
   <property name="map">
       <map>
           <entry key="" value />
           <entry key="" value />
           <entry key="" value />
           <entry key="" value />
       </map>
   </property>
      <property name="pros">
       <props>
           <prop key="">value</prop>
           <prop key="">value</prop>
           <prop key="">value</prop>
       </props>
   </property>
</bean>

tips:注入集合,如果集合是引用类型(对象),则在后加入ref属性

<ref bean = "beanID">

第三方资源配置管理

Spring管理第三方资源,比如第三方连接池:DruidDataSource,CombePooledDataSource(C3P0),通过在配置文件的bean 设置ID与class(通常尝试去搜索或者猜测判断),进入类中查看方法注入(set or 构造),然后进行对应的注入方法(set-> property,构造方法-> constructor-arg),然后在property中使用name与value与类文件进行数据动态绑定。

加载properties配置信息

首先在与applicationContext.xml(同属于resource目录下)文件中存在一个jdbc.properties的配置文件,然后想要读取:
1.开辟新的命名空间,把第一行的bean换成context

xmlns:context.....\context
xsi:schemaLocation=
http:...context(beans位置替换)

2.使用context命名空间加载properties文件

<context:property-placeHolder location="property文件"/>

3.使用property加载读取属性值

<property name="username" value=${配置文件中的属性}/>

4.为了在某些情况下,配置文件的属性与系统文件的属性发生冲突,导致配置文件属性失效,为了有效解决这个问题,需要在命名空间加入system-properties-mode属性,值为NERVER,即系统属性不生效。
<context:property-placeHolder location="classpath:property文件" system-properties-mode=“NERVER”/>

5.为了加载多个配置文件,可以在多个location属性上的多个配置文件中间加逗号,当然可以使用通配符*.properties加载所有配置文件,当然,有时候第三方jar包也存在配置文件,这样要读取所有路径上的所有配置文件,需要这样写:classpath*😗.property文件

创建容器,可以加载多个配置文件,中间使用逗号隔开。
ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml",“xxxx.xml”);

获取bean
1.通过名称获取:
BookDao bookdao = (BookDao)ctx.getBean("bookDao");//这里引用的是ID
2.获取bean并指定类型

BookDao bookdao = (BookDao)ctx.getBean("bookDao", BookDao.class);//这里引用的是ID
3.通过类型进行获取

BookDao bookdao = (BookDao)ctx.getBean(BookDao.class);//这里引用的是ID

tips:按照类型查找的话,这个容器的类型只能有一个

注解开发

在类文件的类前通过注释@Component代替之前的配置文件中标签的配置内容,当前,使用@Component("Dao")可以直接在容器中直接通过名称进行创建,而使用@Component则需要使用指定类型方法进行创建(上一节第三种bean的获取方式)。
核心文件需要在配置文件中通过组件扫描进行注册组件,在配置文件中这样进行配置,是在通过命名空间context进行实现的:
<context:component-scan base-package="com.packagename">
当然,为了能够更清晰的表现各个模块的注解,Spring提供了@Component的三个衍生注释,这三个注释的功能与@Component的功能完全一样,只是为了区分使用的场景:其中,@Controller 用于表现层bean的定义,@Service,用于业务层bean的定义,@Repository,用于数据层bean的定义

纯注解开发

之前我们使用application.xml的方式去获取容器,里面有很多代码,在开发中,为了简化开发,我们可以通过新建类并通过注释代替1.0版本的application.xml的配置文件加载方式,操作步骤如下:
1.新建一个类,在类之前通过加入@Configuration用于设置当前类为配置类,使用@Componentscan({1,2,…})进行组件扫描,括号内为组件扫描的包名
同时,在获取容器时使用注解配置类进行获取:

ApplicationContext ctx = new AnnotationConfigApplicationContext(类名.class);

注释开发bean的作用范围以及生命周期

在实现类前使用@Scope(“singleton”/“prototype”)决定创建对象是否相同,在组件层@Component的类中,通过自定义初始化与销毁的方法,在方法之前通过注释@postconstruct与@predestory来声明对象的周期方法

使用注解开发依赖注入

在@component及其衍生注释的类中,为了实现对象的注入,会使用自动装配(按类型)注入(@autowired),注意,这里是运用反射原理暴力反射为私有初始化,无需使用set方法(构造器也不用了,经典以前白学系列),装配指定的bean,需要使用@Qualifier(‘属性名’)(这个属性名,就是组件里面的括号名称,即1.0配置文件的ID),但是它不可单独进行使用,需要配合上述的@autowired进行使用
引用类型的注入如上,那么简单类型的注入呢,在属性名中,在声明变量前使用@Value()即可:

@Value("1000")
private String num

当然,这种形式是写死的,有时候,我们为了加载外部的properties文件,动态的读取,在注释开发应该怎么做呢?
首先,在配置类中,使用@PropertySource(“配置文件”),然后在@Value中使用 去 引 用 。 ‘ @ V a l u e ( " {}去引用。 `@Value(" @Value("{name}")如果配置文件有多个,则应该加上数组,隔开写,同时,文件不支持通配符,即在1.0时候的*.properties的加载方式在纯注释里不再管用@PropertySource({“配置文件1”,“配置文件2”,…})`

第三方bean的管理,之前的第三方数据库连接为例

使用@bean方法,定义一个方法即可,这个方法的返回值就是你定义的那个对象类型(dataSource),当然,我们不建议将这些代码直接写进配置类,而是新建一个类

public class JDBCconfig{
    @bean
    public DataSource datasource(){
        DruidDataSource ds= new DruidDataSource()
        ...
        return ds
    }
}

然后在配置类中使用@import(JDBCconfig.class)进行导入即可,如果含有多个配置文件,则使用{}的形式进行依次添加。
当然,这样会存在一个问题,如果里面的数据缺少简单类型或者引用对象类型怎么办,简单类型这样做(成员变量)。
由于之前的是这样的:

@bean
public DataSource datasource(){
        DruidDataSource ds= new DruidDataSource()
        ds.setuser("user");
        ds.setpassword("1234");
        return ds
    }

这样不利于数据的存储与写入,我们结合之前的property文件的读取方式还改进:

@Value("")
private String user;
@Value("")
private String password;
@bean
public DataSource datasource(){
        DruidDataSource ds= new DruidDataSource()
        ds.setuser(user);
        ds.setpassword(password);
        return ds
    }

而引用类型这样做:

@Value("")
private String user;
@Value("")
private String password;
@bean
public DataSource datasource(BookDao bookdao){
        DruidDataSource ds= new DruidDataSource()
        ds.setuser(user);
        ds.setpassword(password);
        return ds
    }

是的,直接加入形参即可,方法已经实现自动装配(是通过搜索组件component及其衍生组件的注册进行扫描查找得到进行的自动装配)(方法形参)

AOP

面向切面编程,在不动原始代码的基础上,进行功能增强,有点python装饰器的味道
核心概念:
连接点:程序执行过程中的任意位置
切入点:匹配连接点的式子
通知:在切入点执行的操作,一般是共性操作
通知类:定义通知的类
切面:描述通知与切入点的任意位置

简而言之,就是提取共性的模块,将模块加入到公共的方法中,使之共性的模块能够实现一样的功能。当然也可以实现不同的功能

AOP入门案例

1.导入aspect的包(aspectjweaver)
2.定义接口与实现类:

intelface BookDao(){
    public void update();
    public void save();
}

@component
public class BookDaoimpl implements BookDao{
    public void save(){
        共性功能
        打印
    }
    public void update(){
        共性功能
        打印
    }
}

3.新建一个通知类,在类中起一个方法,将共性功能写进去

public class Myadvice{
    public void bdfore(){
        共性功能
    }
}

4.定义切入点。在哪个类的什么方法生效
定义一个私有方法,无参,无方法体,无返回值

public class Myadvice{

    @Pointcut(execution("void com.package.dao.BookDao.update()"))
    private void pt(){}
    
    public void bdfore(){
        共性功能
    }
}

5.绑定切入点与通知之间的关系,在指定位置之前执行功能

public class Myadvice{

    @Pointcut(execution("void com.package.dao.BookDao.update()"))
    private void pt(){}
    
    @before("pt()")
    public void bdfore(){
        共性功能
    }
}

6.加载注释@component成为Spring能够识别的bean,添加@aspect让程序识别他是AOP

@Component
@Aspect
public class Myadvice{

    @Pointcut(execution("void com.package.dao.BookDao.update()"))
    private void pt(){}
    
    @before("pt()")
    public void bdfore(){
        共性功能
    }
}

7.开启配置对AOP的注释驱动支持@EnableAspectJAuoProxy

@Configuration
@ComponentScan("com.package")
@EnableAspectJAuoProxy
public class springconfig{
}

AOP核心:代理模式

切入点表达式

切入点表达式可以匹配接口类,也可以匹配实现类
可以使用通配符*进行匹配,任意参数使用…代替

AOP通知类型:
前置@before,后置@after 环绕@around,其中环绕比较重要

@Around("pt()")
public Object around(ProceedingJoinPoint pjb) throws Throwsable{
    前
    object s = pjb.proceed();
    后
    return s
}

如果原来的函数有返回值类型,则AOP的返回类型一定为Object,且加入形参ProceedingJoinPoint,没有返回值类型为void。
在环绕通知中,signature可以配合ProceedingJoinPoint,显示本次具体执行的是什么方法,什么类额度相关信息

AOP通知获取数据

获取切入点方法返回值
返回后通知(较少用),环绕通知(常用)
获取切入点的方法参数
JoinPoint(适用于前置,后置,返回后,抛出异常)
ProceedingJoinPoint(适用于环绕)
获取切入点的异常信息
抛出异常后通知
环绕通知
可以看到,环绕通知比较多,详细掌握它就可以了

AOP这个操作可以对原始的数据进行修改校验,并返回,相当于拦截器,非常实用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值