加入收藏 | 设为首页 | 会员中心 | 我要投稿 我爱制作网_潮州站长网 (http://www.0768zz.com/)- 物联安全、建站、操作系统、云计算、数据迁移!
当前位置: 首页 > 教程 > 正文

Spring IOC 配置分析

发布时间:2021-12-09 20:06:40 所属栏目:教程 来源:互联网
导读:1 IOC概述 1.1 IOC概念 IOC中文是控制反转,即是某一接口具体实现类的选择控制权从调用类中移除,转交给第三方决定。从而解除了某一接口对实现类的直接依赖。 1.2 IOC类型 主要分为构造函数注入,属性注入,接口注入 构造函数注入 public class Bar { privat

1 IOC概述
1.1 IOC概念
IOC中文是控制反转,即是某一接口具体实现类的选择控制权从调用类中移除,转交给第三方决定。从而解除了某一接口对实现类的直接依赖。
 
1.2 IOC类型
主要分为构造函数注入,属性注入,接口注入
 
构造函数注入
 
public class Bar {
 
    private Foo foo;
 
    public Bar(Foo foo) {
        this.foo = foo;
    }
}
属性注入
 
public class Bar {
 
    private Foo foo;
 
    public void setFoo(Foo foo) {
        this.foo = foo;
    }
}
接口注入
 
public interface BarInterface {
    void setFoo(Foo foo);
}
public class Bar implements BarInterface {
 
    private Foo foo;
 
    public void setFoo(Foo foo) {
        this.foo = foo;
    }
}
此种方式和属性注入没有明显区别,但是却增加了一个接口,这不利于项目后期的维护,因此不建议使用!
 
1.3 spring的IOC配置
<?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 ">
    <bean id="foo" class="org.acy.di.Foo"/>
    <bean id="bar" class="org.acy.di.Bar">
        <property name="foo" ref="foo"/>
    </bean>
</beans>
2 spring的资源访问
2.1 资源抽象接口
Spring的Resource接口,使应用访问底层资源更加便捷。
主要方法:
-boolean exists() 是否存在
-boolean isOpen()
-URL getURL()
-File getFile()
-InputStream getInputStream()
 
这个接口下面主要的实现类有:
 
ByteArrayResource:内存资源
ClassPathResource:类路径下的资源
FileSystemResource:文件系统资源
InputStreamResource:输入流资源
ServletContextResource:Web容器上下文资源
UrlResource:远程资源
测试1
 
public class FileSourceExample {
 
    public static void main(String[] args) {
        String filePath = "C:UsersAdministratorIdeaProjectsspringc03srcmainresources1.txt";
        Resource resource1 = new FileSystemResource(filePath);
        System.out.println(resource1.getFilename());
 
        Resource resource = new ClassPathResource("1.txt");
        System.out.println(resource.getFilename());
    }
}
测试2
 
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    Resource resource = new ServletContextResource(application, "/WEB-INF/classes/1.txt");
%>
<%=resource.getFilename()%>
<%=WebUtils.getTempDir(application).getAbsolutePath()%>
</body>
</html>
测试3
 
public class EncodedTest {
    public static void main(String[] args) throws IOException {
        Resource resource = new ClassPathResource("1.txt");
        EncodedResource encodedResource = new EncodedResource(resource,"utf-8");
        String s = FileCopyUtils.copyToString(encodedResource.getReader());
        System.out.println(s);
    }
}
注:资源加载时默认采用系统编码读取资源,如果需要转码,可用EncodedResource
 
2.2资源加载
资源地址表达式
 
classpath: 从类的跟路径加载
file: 从文件路径
http: http协议
ftp: ftp协议加载
没有前缀 则根据当前实用的ApplicationConext实现类决定
"classpath*:"相对于"classpath:"的优势在于:如果有同包名的资源文件,分别打成了两个jar包【a.jar和b.jar】。
用"classpath:"只加在a.jar中的资源文件。用"classpath*:"会加载a b两个jar包的配置文件
匹配符
? :一个字符
* :多个字符
** :多级目录
 
资源加载器
ResourceLoader:可以根据资源地址加载一个资源,但不支持匹配符
ResourcePatternResolver:支持匹配符
PathMatchingResourcePatternResolver:Spring的标准实现,也支持匹配符
 
public class ResolverTest {
    public static void main(String[] args) throws IOException {
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = resolver.getResources("classpath*:org/acy/**/*.xml");
        for (Resource resource : resources) {
            System.out.println(resource.getFilename());
        }
    }
}
3 BeanFactory与ApplicationContext
3.1 BeanFactory解读
BeanFactory是一个工厂,用于创造各种类型的对象。
BeanFactory体系结构
BeanFactory:底层接口
ListableBeanFactory:增加访问容器中Bean基本信息的方法 如bean的个数,是否包含等。
HierarchicalBeanFactory:父子容器级联接口,使子容器可以访问父容器。
ConfigurableBeanFactory:重要接口,增强了IOC的定制化,加入了类装载器、属性编辑器、容器初始化后置处理器的方法
AutowireCapableBeanFactory:加入自动装配
 
测试
 
public class BeanFactoryTest {
    public static void main(String[] args) {
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource resource = resolver.getResource("classpath:applicationContext.xml");
        BeanFactory beanFactory = new XmlBeanFactory(resource);
        System.out.println("BeanFactory 初始化完成");
 
        Car car = beanFactory.getBean("car", Car.class);
        System.out.println(car);
    }
}
注:以上使用了XmlBeanFactory,其为上面那些接口的最终实现类。用BeanFactory会导致Bean在容器启动时候不会主动初始化,而是等到第一次使用时候在初始化。
 
3.2 ApplicationContext介绍
主要实现类有ClasspathXmlApplicationContext与FileSystemXmlApplicationContext,且ApplicationContext所有实现类都实现了ResourcePatternResolver接口,可以接受匹配符表达式加载资源文件。
并且ConfigurableApplicationContext还加入了refresh()和close(),用于刷新和关闭容器。
ApplicationContext是在容器启动时初始化所有Bean
 
注解配置
 
@Configuration
public class Beans {
    @Bean(name = "car")
    public Car buildCar() {
        Car car = new Car();
        car.setBrand("三轮车");
        car.setColor("red");
        car.setMaxSpeed(200);
        return car;
    }
}
public class AnnoTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(Beans.class);
        Car car = context.getBean("car", Car.class);
        System.out.println(car);
    }
}
WebApplicationContext
WebApplicationContext是存储在ServletContext中,所有可以再任何代码中取出实用。
WebApplicationContextUtils.getWebApplicationContext(ServletContext sc)
 
WebApplicationContext初始化
在Web.xml配置监听器
ContextLoaderListener
 
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
如果不支持Listener,则可以使用ContextLoaderServlet
 
以上配置,Spring会默认采用XmlWebApplicationContext,如果要采用注解,可以实用如下配置
 
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>org.acy.anno.Beans</param-value>
    </context-param>
4 Bean生命周期
Bean的作用范围
实例化Bean时所经历的一系列阶段
 
4.1 BeanFactory的生命周期
关键点:
 
Bean自身的方法:如实例化,setter,或者init method和destroy method
Bean级别生命周期接口方法: BeanNameAware BeanFactoryAware InitializingBean和DisposableBean
重点 容器级生命周期接口方法 InstantiationAwareBeanPostProcessor和BeanPostProcessor,这些接口的实现类为单独的组件,实现后注册到容器上即可。[属于插件机制]
可以注册多个同种接口的实现类,但是必须实现Ordered接口排序。
新版本中还加入了InstantiationAwareBeanPostProcessorAdapter抽象类
 
 
 
例子
 
public class Cat implements BeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean {
 
    private String brand;
 
    private String color;
 
    private int maxSpeed;
 
    public Cat() {
 
    }
 
    public Cat(String brand, String color, int maxSpeed) {
        this.brand = brand;
        this.color = color;
        this.maxSpeed = maxSpeed;
    }
 
    public void introduce() {
        System.out.println(this.toString());
    }
 
    public String getBrand() {
        return brand;
    }
 
    public void setBrand(String brand) {
        this.brand = brand;
    }
 
    public String getColor() {
        return color;
    }
 
    public void setColor(String color) {
        this.color = color;
    }
 
    public int getMaxSpeed() {
        return maxSpeed;
    }
 
    public void setMaxSpeed(int maxSpeed) {
        this.maxSpeed = maxSpeed;
    }
 
    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + ''' +
                ", color='" + color + ''' +
                ", maxSpeed=" + maxSpeed +
                '}';
    }
 
    private BeanFactory beanFactory;
 
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("setBeanFactory");
        this.beanFactory = beanFactory;
    }
 
    private String beanName;
 
    public void setBeanName(String s) {
        System.out.println("setBeanName");
        this.beanName = s;
    }
 
    public void destroy() throws Exception {
        System.out.println("destroy");
    }
 
    public void afterPropertiesSet() throws Exception {
        System.out.println("afterPropertiesSet");
    }
 
    public void myInit(){
        System.out.println("myInit");
        this.setMaxSpeed(240);
    }
 
    public void myDestroy(){
        System.out.println("myDestroy");
    }
}
public class MyBeanPostProcessor implements BeanPostProcessor {
 
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("cat".equals(beanName)) {
            Cat cat = (Cat) bean;
            if (cat.getColor() == null) {
                System.out.println("color 为空 设为黑色");
                cat.setColor("black");
            }
        }
        return bean;
    }
 
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("cat".equals(beanName)) {
            Cat cat = (Cat) bean;
            if (cat.getMaxSpeed() > 200) {
                System.out.println("speed great then 200");
                cat.setMaxSpeed(200);
            }
        }
        return bean;
    }
}
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
 
    @Override
    public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
        if ("cat".equals(beanName)){
            System.out.println("postProcessBeforeInstantiation");
        }
        return null;
    }
 
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if ("cat".equals(beanName)){
            System.out.println("postProcessAfterInstantiation");
        }
        return true;
    }
 
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        if ("cat".equals(beanName)){
            System.out.println("postProcessPropertyValues");
        }
        return pvs;
    }
}
public class BeanCycle {
    public static void main(String[] args) {
        Resource res = new ClassPathResource("applicationContext.xml");
        XmlBeanFactory beanFactory = new XmlBeanFactory(res);
        ConfigurableBeanFactory configurableBeanFactory = beanFactory;
        configurableBeanFactory.addBeanPostProcessor(new MyBeanPostProcessor());
        configurableBeanFactory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());
 
        Cat cat = beanFactory.getBean("cat", Cat.class);
        System.out.println(cat);
        cat.setColor("yellow");
        Cat c2 = beanFactory.getBean("cat", Cat.class);
        System.out.println(cat == c2);
        beanFactory.destroySingletons();
    }
}
以上例子简单打印了一些spring的生命周期信息,并且有一些先后顺序。在新版本中 init method和destroy method的配置改为@PostConstruct和@PreDestroy注解配置。
BeanPostProcessor是一个扩展Spring的重要接口。
 
4.2 ApplicationContext的生命周期
加入了一个新接口ApplicationContextAware 用户注入ApplicationContext。
 
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("cat");
        beanDefinition.getPropertyValues().addPropertyValue("brand","奇瑞qq");
        System.out.println("postProcessBeanFactory");
    }
}
BeanFactoryPostProcessor实在最开始执行的,可以在对象实例化后,有线修改。在Bean被Spring加载后,会生成一个BeanDefinition
 
    <bean id="cat" class="org.acy.bfc.Cat" init-method="myInit" destroy-method="myDestroy">
        <property name="brand" value="奔驰"/>
        <property name="color" value="黑色"/>
        <property name="maxSpeed" value="200"/>
    </bean>
 
    <bean class="org.acy.bfc.MyBeanPostProcessor"/>
    <bean class="org.acy.bfc.MyBeanFactoryPostProcessor"/>
此处配置了一些Processor,ApplicationContext在启动时候会自动加载这些Processor。

(编辑:我爱制作网_潮州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读