补充:scope 的prototype 容器初始化时不创建bean实例,而是每次请求时都会创建实例。

bean使用外部属性文件
spring2.5之后使用 使用 context:property-placeholder location=""
当然要使用这个就得加上命名空间,不然程序可不知道这是什么标签。
xmlns:context="http://www.springframework.org/schema/context"
<?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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
        <!-- 这里指明 外部属性文件的路径 可以是下面的情况也可以是 相对路径 URL-->
        <!-- 例子:location="/test.properties" 应为当前文件和 test.properties都在src-->
<context:property-placeholder location="classpath:test.properties"/>
<bean id="property" class="SQLConnet.PropertyDemo">
    <property name="name" value="${name}"></property>
    <property name="password" value="${password}"></property>
</bean>

</beans>

这里 ${name}就是获取的外部 (test.properties文件的 name)

name=v5_BAT
password=123456

这么做有什么优点呢:当你的配置文件特别大的时候,再去修改配置文件找到对应的代码就比较耗时了。那么去修改一个外部的文件就显得轻松很多了。

SpEL
-字面值
整数<property name="spel" value="#{5}">
浮点<property name="spel" value="#{5.5}">
科学记数法<property name="spel" value="#{5}">
字符串(使用单引号 或者双引号)
<property name="spel" value="#{"hello spring"}">
<property name="spel" value="#{'hello spring'}">
boolean
<property name="spel" value="#{false}">

-引用bean 相当于ref

<property name="spel" value="#{otherbeanid}">
引用其他bean的属性
<property name="spel" value="#{otherbeanid.name}">
引用其他bean的方法的返回值
<property name="spel" value="#{otherbeanid.hello()}">

等等 简单点说SpEL#{} 花括号内就相当于一个方法体 方法体中可以写的东西基本上都可以 什么 +-*/ 调用方法 if else 三目运算符 。。。。

这里要注意一下调用静态方法 :
T(全类名).静态方法或者属性

IOC容器管理bean的生命周期
-在bean中还有两个属性:init-method 和 destroy-method 来指定在bean创建事初始化和销毁时执行的代码。
新建测试类 这里多了两个方法 :init() destory()  (名字自拟)
package Test;

public class LifeDemo {

    private int age;

    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
        System.out.println("this is setway");
    }
    public LifeDemo() {
        // TODO Auto-generated constructor stub
        System.out.println("this is constructor");
    }
    private void init() {
        // TODO Auto-generated method stub
        System.out.println("this is initway");

    }
    private void destory() {
        // TODO Auto-generated method stub
        System.out.println("this is destoryway");

    }
}

bean 的写法就是多了 两个属性 属性值分别是 我在该类中创建的

 <bean id="lifeDemo" class="Test.LifeDemo"
        init-method="init"
        destroy-method="destory"
    >
        <property name="age" value="20"></property>

    </bean>

测试类

package Test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

    public static void main(String[] args) {

        ClassPathXmlApplicationContext ioc=new ClassPathXmlApplicationContext("lifeContext.xml");
        LifeDemo ld=(LifeDemo) ioc.getBean("lifeDemo");

        ioc.close();

    }
}

结果:
this is constructor
this is setway
this is initway
this is destoryway

先分析一下结果: 在在set方法执行之后执行 init-method所指定的方法(类初始化的时候执行)。在调用close方法之后执行。

    ClassPathXmlApplicationContext ioc=new ClassPathXmlApplicationContext("lifeContext.xml");

细心的人会发现前面都用的是 ApplicationContext 现在怎么换了。下面给大家梳理一下类的层次结构

BeanFoctory  (I)
     |-ApplicationContext (I)
         |-ClassPathXmlApplicationContext (C)  
         |-FileSystemXmlApplicationContext (C)

这里为什么不用接口不用说肯定是用到实现类的特有方法。

-bean的后置处理器

后置处理器需要一个类来实现beanPostProcessor 可见是源码是用 钩子模式实现的。
不多说先创建一个类实现一下。
住:后置处理器是处理所有bean 的

package Test;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPostProcessor implements BeanPostProcessor {

     /**
     *实现接口的两方法
     *第一个参数是当前使用后置处理器的bean实例
     *第二个参数是当前bean id
     *
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanname)
            throws BeansException {
        System.out.println("this is aferinitway" +bean+"    "+beanname);
        return bean;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanname)
            throws BeansException {
        System.out.println("this is beforeinitway" +bean+"    "+beanname);
        return bean;
    }

}
<bean id="lifeDemo" class="Test.LifeDemo"
        init-method="init"
        destroy-method="destory"
    >
        <property name="age" value="20"></property>

    </bean>
    <!--增加下面的配置-->
<bean class="Test.MyBeanPostProcessor"></bean>

结果

this is constructor
this is setway
this is beforeinitwayTest.LifeDemo@6e06451e    lifeDemo
this is initway
this is aferinitwayTest.LifeDemo@6e06451e    lifeDemo
this is destoryway

结果显而易见什么时候调用都清楚。
发现处理器处理以后返回的是bean实例。那么也就可以对bean实例进行更改。如果不返回会怎么样呢(会抛出异常)后面就没有这个bean实例。

通过工厂配置bean
用到的任然是bean的属性 factory-method .来指定嗲用工厂的方法产生实例。
当然你要使用工厂就能有个可用的工厂实例 或者 静态的方法  
如果需要创建工厂实例 用bean 创建  然后在使用的地方加上 factory-bean="factorybeanid"
其他不变。
如果是一个静态工厂就更简单了直接使用如下
    <bean id="lifeDemo1" 
     class="Factory.StaticFactory"
     factory-method="getLifeDemoInstance"
    >
    <!--方法的参数放在这里-->
    <constructor-arg value="first"></constructor-arg>
    </bean>
通过FatoryBean 配置bean

首先要有一个类实现FactoryBean

package Factory;

import org.springframework.beans.factory.FactoryBean;

import Test.LifeDemo;

public class MyFactoryBean implements FactoryBean<LifeDemo> {

    private int age;
    public void setAge(int age){
        this.age=age;

    }
    @Override
    public LifeDemo getObject() throws Exception {
        // TODO Auto-generated method stub
        return new LifeDemo(age);
    }

    @Override
    public Class<?> getObjectType() {
        // TODO Auto-generated method stub
        return LifeDemo.class;
    }

    @Override
    public boolean isSingleton() {
        // TODO Auto-generated method stub
        return true;
    }

}

配置直接使用我们实现的类

<bean id="life" class="Factory.MyFactoryBean">
        <property name="age" value="20"></property>
    </bean>

底层会自动调用 getObject() 并吧获得的实例作为bean实例

通过注解来配置bean

住:这里如果没导入aop的包 会报 classnotfound org/springframework/aop/TargetSource 的错误。导入一下jar包就行了。

前面用的都是xml来配置现在讲一种更简单的方法通过注解

bean注解 声明

@Component 标示 是Spring管理的组件
@Repositroy 在数据访问层、持久化层 dao
@Service  业务逻辑层
@Controller 表现层

在类上声明这个类就是spring 管理的类了。
当然不是用注解就没有xml的事了。我们仍然要在spring的配置文件中 加上点东西

<context:component-scan base-package="这里填上父包"></context:component-scan>

这样就会扫描父包及其以下的所有被spring管理的包(有声明的、有注解的)

在c测试类中我们又该怎么拿到这个bean的实例呢

1.spring 默认的命名规则为被注解的类 首字母小写(UserController->userController)
2.可以自己命名(@Repositroy(controller))
命名以后就相当于id 可以通过getBean(id)来获取实例

如果不想都扫描我们就可以对其中做一些限定

<context:component-scan base-package="这里填上父包"
resource-pattern="/*.class"
//指定扫描的资源
></context:component-scan>

还有可以根据 annotation 来指定
同理
<context:component-scan base-package="这里填上父包">
<ontext:exclude-filter type="annotation"
 expression="....Repository"
</context:component-scan>
有exclude就有include 意思是只有这个可以
当然要使用include 要 包默认的过滤器改为false
<context:component-scan base-package="这里填上父包"
use-default-filter="false"
>
<ontext:exclude-filter type="annotation"
 expression="....Repository"
</context:component-scan>

type 中还assingable 这个是对类进行限制同理很容易使用

对bean进行注入少不了bean之间的组合;
package BeanByAnnotation.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import BeanByAnnotation.respository.UserRes;

@Service
public class MyServcieImpel implements myservice {

/**
这里只要在组合的地方加上@Autowired注解即可 (有没有set方法都一样 底层只是找到要注解什么bean 不会去执行set方法来注入)。找到要注入对象spring会去容器中查找是否有对应兼容的bean (为什么说是兼容 有的bean是实现一些接口)找到就注入。
如果没找到会抛出异常。如果不想抛出异常可以@Autowired(require=false)这样如果没找到这个实例就是null
那又如果有很多bean都是兼容的就要根据命名来判断是哪一个了。如果只声明没有指明具体的名字就会默认为首字母小写前面提到过 。
解决方法@Qualifier("指定名字") 可以写在属性  方法上 甚至 set方法传入的参数上

*/
    @Autowired
    private UserRes userRes;
    public void setUserRes(UserRes userRes){
        this.userRes=userRes;
    }
    @Override
    public void print() {
        // TODO Auto-generated method stub
        System.out.println("servcie print");
        userRes.save();

    }

}

spring4.x的新特性
泛型依赖注入
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐