spring入门专题一(ioc之接口及面向接口编程)

spring的概况:spring是一个开源框架,为了解决企业应用开发的复杂性而创建的,但现在不止用于企业应用
spring事业一个轻量级的ioc(控住反转)和aop面向切面 的容器框架。
1:从大小和开销两方面而言Spring都是轻量级的
2:通过控制反转(ioc)技术达到松耦合的目的
3:提供面向切面的编程的丰富支持,允许通过分离应用的业务逻辑于系统级服务进行内聚性的开发区
4:包含并管理应用对象的配置和生命周期,这个意义上是一个容器
5:将简单的组件配置 ,组合成复杂的应用,这个意义上是框架。

spring的结构图:

image.png
spring的作用 :

1: 容器
2:提供对多种技术的支持(jms mq UnitTest。。。。。。)
3:Aop(事务管理,日志)
4:提供众多的方便应用的辅助类(JDBC Template)
5:对主流框架良好的支持(hihibernate等)

spring的适用范围

1:构建企业级应用(ssm,ssh)
2:单独使用bean容器(bean的管理)
3:单独使用Aop进行切面管理
4:其他Spring的功能(如对消息的支持)
5:在互联网中的应用。

什么是框架

特点:1半成品
2封装了特定的处理流程和控制逻辑
3成熟的,不断升级改进的软件
框架和类库的区别
1框架一般封装了逻辑,高内聚的,类库则是松散的工具组合。
2框架专注于某一领域,类库更加的通用。

接口

1用于沟通中介物的抽象化
2实体把自己提供给外界的一种抽象化说明,用以由内部操作分离出外部沟通的方法,使其能够被修改内部而不影响外界其他的实体与之与其交互的方式
3对应java接口及声明,声明了哪些方法对外提供.
4在java8中接口拥有方法体

面向接口编程

1结构设计中,分清层次及调用关系。每层只向外(上层)提供一组功能的接口,各层间依赖接口并非实现类
2:接口实现变动不影响各层间的调用,这一点在公共服务中尤为的重要 。
3:面向接口编程中的接口是用于隐藏具体实现和实现多态性的组件

例子:
public interface OneInterface{
    String hello(String word);
}

public class OneInterfaceImpl implements OneInterface{
    @Overiide
    public String hello(String word){
    return "OneInterface"+word;
    }
    public static void main(String[] args){
     OneInterfaceImpl  one=new OneInterfaceImpl();
    System.out.println(one.hello("word"));
    }
}
什么是ioc:

控制反转,控制权的转移,应用程序本身不负责依赖对象的创建和维护,而是由外部容器负责依赖和维护的
Di(依赖注入)是一种实现方式
目的:创建对象并组装对象之间的关系


image.png

(获得依赖对象的过程被反转了,这个过程由自身管理变成了由Ioc容器主动注入)

spring中bean的配置(两种方式1配置 2注解)、

1:配置方式

<?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:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
    >
//命名空间
    <bean id="pooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    //声明一个bean ,id为唯一标识,class对于具体的类 
    </bean>
</beans>
单元测试

1:下载junit并引入jar包
2:创建UnitTestBean类,完成对Spring配置文件的加载,销毁
3:所有单元测试类都要继承自UnitTestBean类,通过他的getBean方法获取想要得到的对象
4:子类(具体执行单元测试的类)加注解:
@RunWith(BlockJUnit4ClassRunner.class)
5:单元测试的方法加注解:@Test
6:右键选择要执行的单元测试方法执行或执行一个类全部的单元测试方法。
具体的代码:

public class UnitTestBase {
    
    private ClassPathXmlApplicationContext context;
    
    private String springXmlpath;
    
    public UnitTestBase() {}
    
    public UnitTestBase(String springXmlpath) {
        this.springXmlpath = springXmlpath;
    }
    
    @Before
    public void before() {
        if (StringUtils.isEmpty(springXmlpath)) {
            springXmlpath = "classpath*:spring-*.xml";
        }
        try {
            context = new ClassPathXmlApplicationContext(springXmlpath.split("[,\\s]+"));
            context.start();
        } catch (BeansException e) {
            e.printStackTrace();
        }
    }
    
    @After
    public void after() {
        context.destroy();
    }
    
    @SuppressWarnings("unchecked")
    protected <T extends Object> T getBean(String beanId) {
        try {
            return (T)context.getBean(beanId);
        } catch (BeansException e) {
            e.printStackTrace();
            return null;
        }
    }
    
    protected <T extends Object> T getBean(Class<T> clazz) {
        try {
            return context.getBean(clazz);
        } catch (BeansException e) {
            e.printStackTrace();
            return null;
        }
    }

}
测试类:
@RunWith(BlockJUnit4ClassRunner.class)
public class TestOneInterface extends UnitTestBase {

    public TestOneInterface() {
        super("classpath:spring-ioc.xml");
    }
    
    @Test
    public void testSay() {
        OneInterface oneInterface = super.getBean("oneInterface");
        oneInterface.say("This is a test.");
    }

}

bean容器的初始化过程

基础两个包
-org.springframework.beans
-org.springframework.context
-BeanFactory提供配置结构和基本功能,加载并初始化Bean
-ApplicationContext保存了Bean对象并在spring中被广泛的使用

加载方式-ApplicationContext

-本地文件
-Classpath
-Web应用中依赖servlet或Listener

案例:
1文件:
    FileSystemXmlApplicationContext context=new FileSystemXmlApplicationContext("F:/Spring/src/main/resources/spring-ioc.xml");
2classpath:
    ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("classpath:spring-ioc.xml");
3web应用
<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <!--2 -->

    <servlet>
        <servlet-name>context</servlet-name>
        <servlet-class>org.springframework.web.context.ContextloaderServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
//有两个类分别为ContextLoaderListener和ContextloaderServlet,都可以加载配置文件。

spring的注入

spring注入是指在启动spring容器加载bean配置的时候,完成对变量的赋值

常用的两种方式

1:设置注入
2:构造注入

设置注入
<bean id="DAO" class="com.atguigu.crud.bean.InjectionDAO">  
</bean>
<bean id="ServiceImpl " class="com.atguigu.crud.bean.InjectionServiceImpl ">
        <property name="injectionDAO" ref="DAO"/>
</bean>
设置注入会提前调用属性的set的方法,为属性赋值。
构造注入
<bean id="DAO" class="com.atguigu.crud.bean.InjectionDAO">  
</bean>
<bean id="ServiceImpl " class="com.atguigu.crud.bean.InjectionServiceImpl ">
        <constructor-arg name="injectionDAO" ref="DAO"/>
</bean>
通过调用构造方法进行赋值
代码:
public class InjectionServiceImpl implements InjectionService {
private InjectionDAO injectionDAO;
    
    //构造器注入
    public InjectionServiceImpl(InjectionDAO injectionDAO1) {
        this.injectionDAO = injectionDAO1;
    }
    
    //设值注入
    public void setInjectionDAO(InjectionDAO injectionDAO) {
        this.injectionDAO = injectionDAO;
    }
}
bean的配置项

1:id (唯一标识 )
2:Class(具体类,这个是必须的)
3:Scope(作用域)
4:Constructor argguments(构造器仓鼠)
5:Properties(属性)
6:Autowiring mode(自动装配模式)
7:lazy-initialization mode(懒加载模式)
8:Initalization/destruction method(初始化和销毁的方法)

bean的作用域Scope(五种类型)

1:singleton:单例,指一个bean容器中只存在一份
2:prototype:每次请求(每次使用)创建新的实列,destroy方式不生效
3:request:每次http请求创建一个实列且仅在当前的request内有效
4:session:同上每次http请求创建,当前session内有效
5:global session:基于portlet的web中有效(portlet定义了global session),如果在web中,同session

(如果在单元测试类中用两个测试方法获取同一个id的bean,
会先启动一个ioc容器,关闭后在启动一个,因此如果使用Scope为单例将获得两个不同的bean如下图:)


image.png
bean的生命周期
bean的初始化:(两种)

1:实现org.springframework.beans.factory.InitializingBean接口,覆盖afterPropertiesSet方法


image.png

2:配置Init-method


image.png
bean的销毁:(两种)

1实现org.springframework.beans.factory.DisposableBean接口,覆盖destroy方法


image.png

2:配置Destroy-method


image.png
配置全局默认初始化,销毁方法(可选,没有方法的话,不会报异常,上面两种必须配置方法)
<?xml version="1.0" encoding="UTF-8"?>
<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" 
        default-init-method="defautInit" default-destroy-method="defaultDestroy">
        
        <bean id="beanLifeCycle" class="com.imooc.lifecycle.BeanLifeCycle"  init-method="start" destroy-method="stop"></bean>
    
 </beans>
同时以两种方式创建和初始化bean的时候实现接口优先于配置,当配置了初始化或销毁方法,全局默认将被覆盖

Aware

1:Spring中提供了一些以Aware结尾的接口,实现了Aware接口的bean在被初始化之后,可以获得相应的资源
2:通过Aware接口,可以对Spring相应的资源进行操作(一定要慎重)
3:对Spring进行简单的扩展提供了方便的入口

1 ApplicationContextAware:获取ApplicationContext(上下文路径对象)
2 ApplicationEventPublisherAware
3 BeanClassLoaderAware
4 BeanFactoryAware
5 BeanNameAware:获取BeanName
6 BootstrapContextAware
7 LoadTimeWeaverAware
等等。

bean的自动装配

1:no:不做任何的操作
2:byname: 根据属性名自动装配。此选项将检查容器并根据查找与属性完全一致的bean,并将其与属性自动装配
3:bytype:如果容器中存在一个与指定属性相同的bean,那么将与该属性自动装配;如果存在多个该类型的bean,那么将会抛出异常,并指出不能使用bytype的方式进行自动装配;如果没有找到相应的bean,则什么事情都不会发生
4:Constructor:于bytype的方式类似,不同之处在于它用于构造参数。如果容器没有找到与构造参数类型一致的bean,那么将会抛出异常。

<?xml version="1.0" encoding="UTF-8"?>
<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" 
        default-autowire="constructor"//bytype//byname>
    <bean id="autoWiringService" class="com.imooc.autowiring.AutoWiringService" ></bean>
        
        <bean class="com.imooc.autowiring.AutoWiringDAO" ></bean>
    
 </beans>

以byname和bytype的方式自动装配的话,被引用的类,声明set方法(寻找和id名一样的bean,bytype和bean的id名无关)
以bytype的方式自动装配的话,被引用的类,声明构造方法

public class AutoWiringService {
    
    private AutoWiringDAO autoWiringDAO;
    //Constructor设置构造函数
    public AutoWiringService(AutoWiringDAO autoWiringDAO) {
        System.out.println("AutoWiringService");
        this.autoWiringDAO = autoWiringDAO;
    }
        //byname设置set方法
    public void setAutoWiringDAO(AutoWiringDAO autoWiringDAO) {
        System.out.println("setAutoWiringDAO");
        this.autoWiringDAO = autoWiringDAO;
    }
    
    public void say(String word) {
        this.autoWiringDAO.say(word);
    }

}

文件获取之Resource

针对于资源文件的统一接口

Resource:

1UrlResource:Url对应的资源,根据一个Url地址即可构建
2ClassPathResource:获取类路径文件下的资源文件
3FileSystemResource:获取文件系统里面的资源文件
4ServletContextResource:ServletContext封装的资源,用于访问ServletContext环境下的资源
5InputStreamResource:针对于输入流封装的资源
6ByteArrayResource:针对于字节数组封装的资源

ResourceLoader(对Resource进行资源加载)
spring中所有的application Context都实现了ResourceLoader接口

image.png
输入的路径类型如下图:
image.png

代码如下:

public class MoocResource implements ApplicationContextAware  {
    
    private ApplicationContext applicationContext;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        this.applicationContext = applicationContext;
    }
    
    public void resource() throws IOException {
        Resource resource = applicationContext.getResource("config.txt"//写路径,没有前缀的时候根据classpath来创建的);
        System.out.println(resource.getFilename());
        System.out.println(resource.contentLength());
    }

}
==================================================================================

方式二注解基于注解方式的ioc容器的管理

从spring3.0开始,spring javaConfig项目提供了很多的特征,包括使用java而不是xml来定义bean。
@Component是一个通用的注解,可以用于任何的bean
@Repository通常用于注解dao类,即持久层
@Service通常用于注解Service类,即服务层
@Controller通常用于注解Controller类,即控制层(mvc)


image.png

类的自动检测和注册bean

image.png

标签component-scan会扫描基于类和方法的注解

标签annotation-config只会去扫描类中方法和属性的注解(前者包含后者)

image.png

type的类型有:

image.png

annotation 目标组件中出现在type级别的注释。
assignable 目标组件可分配给(扩展/实现)的类(或接口)(具体的某一个类)。
aspectj 由目标组件匹配的AspectJ类型表达式。
regex 由目标组件类名匹配的正则表达式。
custom :org.springframe .core的自定义实现。TypeFilter接口类型。

image.png

没有指定名称(bean的name属性)的话,默认id为类名首字母小写

自定义命名策略需要指定name-genregenerator为我们需要实现接口的类

image.png
image.png

@Required注解(不常用,了解即可)
1:@Required适用bean属性的set方法
2:这个注解表示,受影响的bean属性必须在配置的时候被填充,通过在bean定义或通过自动装配一个明确的属性值


image.png
@Autowired

1可以将 @Autowired注解在set方法上


image.png

2@Autowired可以用于构造器或者成员变量


image.png

默认情况下,如果找不到合适的bean将会导致@Autowired失败抛出异常,可以通过下面的方式来避免(非必须的,只有在使用的时候发现异常)


image.png
注意点:
1每个类只能有一个构造器被标记为Required=true(默认值为false)
2@Autowired的必要属性,建议使用@Required来代替
image.png

image.png

image.png

image.png

例子:

public interface BeanInterface {

}
@Order(1)
@Component
public class BeanImplTwo implements BeanInterface {

}
@Order(2)
@Component
public class BeanImplOne implements BeanInterface {

}

测试类

@Component
public class BeanInvoker {
    
    @Autowired
    private List<BeanInterface> list;
    
    @Autowired
    private Map<String, BeanInterface> map;
    
    @Autowired
    @Qualifier("beanImplTwo")
    private BeanInterface beanInterface;
    
    public void say() {
        if (null != list && 0 != list.size()) {
            System.out.println("list...");
            for (BeanInterface bean : list) {
                System.out.println(bean.getClass().getName());
            }
        } else {
            System.out.println("List<BeanInterface> list is null !!!!!!!!!!");
        }
        
        System.out.println();
        
        if (null != map && 0 != map.size()) {
            System.out.println("map...");
            for (Map.Entry<String, BeanInterface> entry : map.entrySet()) {
                System.out.println(entry.getKey() + "      " + entry.getValue().getClass().getName());
            }
        } else {
            System.out.println("Map<String, BeanInterface> map is null !!!!!!!!!!");
        }
        
        System.out.println();
        if (null != beanInterface) {
            System.out.println(beanInterface.getClass().getName());
        } else {
            System.out.println("beanInterface is null...");
        }
        
        
    }

输出结果


image.png
@Order只针对list有效,map无效
image.png
xml中定义@qualifier
image.png

image.png

image.png
自定义@qualifier

1:


image.png

2:


image.png
基于java容器的注解@bean
(@Component和@Bean都是用来注册Bean并装配到Spring容器中,但是Bean比Component的自定义性更强。可以实现一些Component实现不了的自定义加载类。)
image.png
如果定义在方法上@bean的名称没有指定名称(默认为方法名)
使用@ImportResource和@Value注解进行资源文件的读取
xml加载资源文件
image.png
注解加载资源文件:
image.png
@Bean和@Scope
image.png
proxyMode代理方式

基于泛型的自动装配


image.png
自定义注解(了解)
image.png
注解@Resource(jsr-250支持)
image.png

(方法名和属性名 )


image.png
回调初始化和销毁
image.png

例子:

@Repository
public class JsrDAO {
    
    public void save() {
        System.out.println("JsrDAO invoked.");
    }
    
}

//@Service
@Named
public class JsrServie {
    
//  @Resource
//  @Inject
    private JsrDAO jsrDAO;
    
//  @Resource
    @Inject
    public void setJsrDAO(@Named("jsrDAO") JsrDAO jsrDAO) {
        this.jsrDAO = jsrDAO;
    }
    
    @PostConstruct
    public void init() {
        System.out.println("JsrServie init.");
    }
    
    @PreDestroy
    public void destroy() {
        System.out.println("JsrServie destroy.");
    }

    public void save() {
        jsrDAO.save();
    }
    
}

执行结果:


image.png

@Autowired和@Resource区别:

1、 @Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上。

2、 @Autowired默认按类型装配(这个注解是属业spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用,如下:

@Autowired()@Qualifier("baseDao")
privateBaseDao baseDao;

3、@Resource(这个注解属于J2EE的),默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

@Resource(name="baseDao")
privateBaseDao baseDao;

总结:

@Autowired//默认按type注入
@Qualifier("cusInfoService")//一般作为@Autowired()的修饰用
@Resource(name="cusInfoService")//默认按name注入,可以通过name和type属性进行选择性注入

一般@Autowired和@Qualifier一起用,@Resource单独用。

当然没有冲突的话@Autowired也可以单独用

@Inject注解

3引入jar包
image.png

image.png

image.png

注解在类上于@Component等效


image.png

总结来源于慕课网免费课程《spring入门篇》。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • 本来是准备看一看Spring源码的。然后在知乎上看到来一个帖子,说有一群**自己连Spring官方文档都没有完全读...
    此鱼不得水阅读 6,925评论 4 21
  • 深入使用 Spring两种后处理器Bean 后处理器容器后处理器属性占位符配置器重写占位符配置器Spring 的自...
    渐丶忘阅读 1,083评论 0 1
  • 来源:关于Spring IOC (DI-依赖注入)你需要知道的一切作者:zejian Dao层(AccountDa...
    杨井阅读 5,324评论 0 27
  • 文章作者:Tyan博客:noahsnail.com | CSDN | 简书 3.9 Annotation-base...
    SnailTyan阅读 1,159评论 0 3
  • 25个经典的Spring面试问答 本人收集了一些在大家在面试时被经常问及的关于Spring的主要问题,这些问题有可...
    杀小贼阅读 682评论 0 2