Spring(IOC)

基础定义

IOC是一种思想,其实现方式多种多样,当前比较流行的方式有两种,依赖注入和依赖查找

  • 依赖查找:容器提供回调接口和上下文环境给组件,程序代码需提供具体的查找方式
  • 依赖注入:程序代码不做代码调查,这些工作由容器自行完成
  • 依赖注入DI是指程序运行过程中,若需要调用另一个对象的协助,无需再代码中创建被调用者,而是依赖于外部容器,由外部容器创建后传递给程序

IOC实现

  • 完整程序实现过程
  1. 导入包文件
    此时需要了解spring的框架如下,依据图例可知最少需要以下核心包:
    spring-beans、spring-context、spring-core、spring-express;
    为了辅助测试辅助包如:
    com.springsource.junit
    com.springsource.org.apache.commons.logging
    com.springsource.org.apache.log4j

    在这里插入图片描述
  1. 创建类与接口
  1. 配置配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"wan
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">
<!--注册service  -->
<bean id="myService" class="com.jd.wang.SomeServiceImpl">
</bean>
</beans>
  • 书写样例
  1. 接口与实现
package com.jd.wang;
public interface ISomeService {
void doSome();
}

package com.jd.wang;
import org.junit.Test;
public class SomeServiceImpl implements ISomeService {
public void doSome() {
// TODO Auto-generated method stub
System.out.println("执行 doSome");
}}
  1. 测试类
package com.jd.wang.test;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import com.jd.wang.ISomeService;
public class MyTest {
@Test
public void test01(){
 //加载容器对象,加载spring配置文件
 ApplicationContext ac = new
 ClassPathXmlApplicationContext("applicationContext.xml");
 ISomeService service = (ISomeService) ac.getBean("myService");
 service.doSome();}
  //ApplicationContext 与BeanFactory容器的区别:
  //1)ApplicationContext容器再进行初始化时会将其中的所有Bean对象进行创建
  //2)BeanFactory容器中的对象,在容器初始化时并不会被创建,而是在真正获取对象时被创建
  @Test
  public void test02(){
  BeanFactory bf = new XmlBeanFactory(new
  ClassPathResource("applicationContext.xml"));
  ISomeService service = (ISomeService) 
  bf.getBean("myService");service.doSome();}
  1. 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"wan
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">
<!--注册service  -->
<bean id="myService" class="com.jd.wang.SomeServiceImpl">
</bean>
</beans>
  • 动态工厂
  1. 工厂类
package com.jd.wang;
public class ServiceFactory {
public SomeServiceImpl getSomeService()
{
	return new SomeServiceImpl();
}
  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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="factory" class="com.jd.wang.ServiceFactory"></bean>
<bean id="myService" factory-bean="factory" factory
method="getSomeService"></bean>
</beans>
  • 静态工厂
  1. 工厂类
	package com.jd.wang;
	public class ServiceFactory
	 {   
    	public static SomeServiceImpl getSomeService()
    	 {
           	 return new SomeServiceImpl();
         }
    }
  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"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="myService" class="com.jd.wang.ServiceFactory" factory-method="getSomeService"></bean>
</beans>
  • bean作用域
  1. 原型模式

原理:
对象的创建时机不是在spring容器初始化时创建,而是在代码真正访问时才创建
配置关注点:

<bean id="myService" class="com.jd.wang.SomeServiceImpl" scope="prototype"></bean> 

测试用例:

ApplicationContext ac = new  ClassPathXmlApplicationContext("com/jd/wang/applicationContext.xml");
ISomeService service = (ISomeService) ac.getBean("myService");
ISomeService service2 = (ISomeService) ac.getBean("myService");
System.out.println(service == service2);//返回值为false
  1. 单例模式

原理:
对象的创建时机是在spring容器初始化时创建
配置关注点:

<bean id="myService" class="com.jd.wang.SomeServiceImpl" scope="singleton"></bean>

测试用例:

ApplicationContext ac = new  ClassPathXmlApplicationContext("com/jd/wang/applicationContext.xml");
ISomeService service = (ISomeService) ac.getBean("myService");
ISomeService service2 = (ISomeService) ac.getBean("myService");
System.out.println(service == service2);//返回为true
  • bean后处理器
  1. 实现自己的bean后处理器
package com.jd.wang;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor {//必须实现BeanPostProcessor
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName)
                        throws BeansException {
                // TODO Auto-generated method stub
                //此处的bean表示当前正在初始化的bean对象
                //此处的beanName表示当前正在初始化的bean对象的id
                System.out.println("before");
                return bean;
        }
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName)
                        throws BeansException {
                // TODO Auto-generated method stub
                //此处的bean与上文的bean有相同的意义
                System.out.println("after");
                return bean;
        }
}
  1. 配置文件
//只需要新增一行:
<bean class="com.jd.wang.MyBeanPostProcessor"></bean>
  1. 测试实例
ApplicationContext ac = new  ClassPathXmlApplicationContext("com/jd/wang/applicationContext.xml");
ISomeService service = (ISomeService) ac.getBean("myService");
service.doSome();
  • 定制bean的生命始末
  1. 定义实体类
package com.jd.wang;
import org.junit.Test;
public class SomeServiceImpl implements ISomeService {
        public SomeServiceImpl()
        {
                System.out.println("创建对象");
        }
        public void doSome() {
                // TODO Auto-generated method stub
                System.out.println("执行 doSome");
        }   
        public void setUp(){
                System.out.println("生命起始");
        }
        public void tearDown(){
                System.out.println("销毁之前");
        }
}
  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"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="myService" class="com.jd.wang.SomeServiceImpl" init-method="setUp" destroy-method="tearDown"></bean>
        <bean class="com.jd.wang.MyBeanPostProcessor"></bean>
</beans>
  1. 配置
ApplicationContext ac = new  ClassPathXmlApplicationContext("com/jd/wang/applicationContext.xml");
ISomeService service = (ISomeService) ac.getBean("myService");
service.doSome();
  • Bean的生命周期
  1. 构造函数
  2. 参数的诸如
  3. 如果实现了BeanNameAware,则可以获取bean的id
  4. 如果实现了BeanFactoryAware,则可以获取BeanFactory容器
  5. bean后处理器的Before方法
  6. 如果实现了InitializingBean则会执行AfterPropertiesSet,标志着初始化执行结束
  7. 执行bean定义的init-method方法
  8. bean后处理器的After方法
  9. 执行业务方法,自定义的方法等
  10. 如果继承了DisposableBean,执行destory方法(销毁之前)
  11. 执行bean定义的destory-method方法
  • 赋值问题

配置文件

<?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="mySchool" class="com.jd.wang.School">
                <property name="name" value="清华大学 "></property>
        </bean>
        <bean id="mySchool2" class="com.jd.wang.School">
                <property name="name" value="北京大学 "></property>
        </bean>
        <bean id="mySome" class="com.jd.wang.Some">
                <property name="schools">
                        <array>
                                <ref bean="mySchool"/>
                                <ref bean="mySchool2"/>
                        </array>
                </property>
                
                <property name="myStrs">
                        <array>
                                <value>中国</value>
                                <value>北京</value>
                        </array>
                
                </property>
                
                <property name="myList">
                        <list>
                                <value>大兴</value>
                                <value>义庄</value>
                        </list>
                </property>
                
                <property name="mySet">
                        <set>
                                <value>大族企业湾</value>
                                <value>10号楼</value>
                        </set>
                </property>
                
                <property name="myMap">
                        <map>
                                <entry key="mobile" value="17809290119"></entry>
                                <entry key="qq" value="1234567"></entry>
                        </map>
                </property>
                
                <property name="myPros">
                        <props>
                                <prop key="education">大学</prop>
                                <prop key="gender">男</prop>
                        </props>
                </property>
  • 自动注入之名称注入
<?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="school" class="com.jd.wang.School">
        <property name="name" value="school"></property>
    </bean>
    <!-- 
        autowire="byName" 会从容器中查找与实体类的域属性名同名的bean的id,并将该bean对象自动注入给该域属性
     -->
        <bean id="myStudent" class="com.jd.wang.Student" autowire="byName">
                <property name="name" value="张三"></property>
                <property name="age" value="23"></property>
        </bean>
</beans>
  • 自动注入之类型注入
<?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="mySchool" class="com.jd.wang.School">
        <property name="name" value="school"></property>
    </bean>
    <!-- 
        autowire="byType" 会从容器中查找与实体类的域属性类型相同的bean,并将其注入给域属性(有多个时会报错)
     -->
        <bean id="myStudent" class="com.jd.wang.Student" autowire="byType">
                <property name="name" value="张三"></property>
                <property name="age" value="23"></property>
        </bean>
</beans>
  • 使用SPEL表达式注入
<?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="myPerson" class="com.jd.wang.Person">
        <property name="pname" value="李四"></property>
        <property name="page" value="#{T(java.lang.Math).random()*50}"></property>
    </bean>
    <!-- 
        autowire="byType" 会从容器中查找与实体类的域属性类型相同的bean,并将其注入给域属性(有多个时会报错)
     -->
        <bean id="myStudent" class="com.jd.wang.Student" autowire="byType">
                <property name="name" value="#{myPerson.pname}"></property>
                <property name="age" value="#{myPerson.page}"></property>
        </bean>
</beans>
  • 使用内部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">
        <bean id="myStudent" class="com.jd.wang.Student">
                <property name="name" value="wang"></property>
                <property name="age" value="23"></property>
                <property name="school">
                        <bean class="com.jd.wang.School">
                        <property name="name" value="清华大学"></property>
                </bean>
                </property>
        </bean>
</beans>
  • 抽象bean
  1. 同类抽象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">
             <bean id="baseStudent" class="com.jd.wang.Student" abstract="true"> //此bean为抽象bean
                     <property name="school" value="清华大学"></property>
                     <property name="department" value="计算机系"></property>
             </bean>
             <bean id="myStudent" parent="baseStudent">
                     <property name="name" value="王斌斌"></property>
                     <property name="age" value="23"></property>
             </bean>
     </beans>
    
  2. 异类抽象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">
         <bean id="base" abstract="true">
             <property name="school" value="清华大学"></property>
             <property name="department" value="计算机系"></property>
         </bean>
             <bean id="myStudent" class="com.jd.wang.Student" parent="base">
                     <property name="name" value="王斌斌"></property>
                     <property name="age" value="23"></property>
             </bean>
             
             <bean id="myTeacher" class="com.jd.wang.Teacher" parent="base">
                     <property name="name" value="Reyco"></property>
                     <property name="workAge" value="18"></property>
             </bean>
     </beans>
    
  • 为应用指定多个配置文件
  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"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
        <import resource="classpath:com/jd/wang/base.xml"/>
        <import resource="classpath:com/jd/wang/bean.xml"/>
</beans>
  1. 应用程序中指定
ApplicationContext ac = new ClassPathXmlApplicationContext("com/jd/wang/spring-base.xml","com/jd/wang/spring-bean.xml");
  1. 通配符指定
ApplicationContext ac = new ClassPathXmlApplicationContext("com/jd/wang/pring-*.xml");
  • 注解
  1. School类定义
package com.jd.wang;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
 
@Component("mySchool")  //表示当前类被spring容器管理
public class School {
        
        @Value("清华大学")
        private String name;
 
        public String getName() {
                return name;
        }
 
        public void setName(String name) {
                this.name = name;
        }
}
  1. Student类
	package com.jd.wang;
	import org.springframework.beans.factory.annotation.Value;
	import org.springframework.stereotype.Component;
	@Component("myStudent")
	public class Student {
	        @Value("张三")
	        private String name;
	        @Value("23")
	        private int age;
	        @Autowired //byType方式的注解式注入
	        @Qualifier("mySchool") //byName方式的注解式注入,要求@Autowired与  @Qualifier联合使用
	       //@Resource(name="mySchool")表示byName @Resource表示byType
	        private School school;
	        private String department;
	        public String getName() {
	                return name;
	        }
	        public void setName(String name) {
	                this.name = name;
	        }
	        public int getAge() {
	                return age;
	        }
	        public void setAge(int age) {
	                this.age = age;
	        }
	        public School getSchool() {
	                return school;
	        }
	        public void setSchool(School school) {
	                this.school = school;
	        }
	        public String getDepartment() {
	                return department;
	        }
	        public void setDepartment(String department) {
	                this.department = department;
	        }
	        @Override
	        public String toString() {
	                return "Student [name=" + name + ", age=" + age + ", school=" + school
	                                + ", department=" + department + "]";
	        }
	}
  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" 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.xsd"> <!-- bean definitions here -->
        <context:component-scan base-package="com.jd.wang"></context:component-scan>//可以使用通配符
</beans>
  • 三种相同的注解
  1. @Repository注解在Dao实现类上
  2. @Service注解在Service实现类上
  3. @Controller注解在SpringMVC的处理器上
    这些注解功能完全相同,只是意义不同
  • bean的生命始末注解
@PostConstruct
public void initAfter()
{
        System.out.println("创建后");
}
@PreDestroy
public void preDestory()
{
        System.out.print("销毁前");
}
  • 使用JavaConfig进行配置
  1. 定义容器类
package com.jd.wang;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyJavaConfig {
        
        @Bean(name="mySchool")
        public School mySchoolCreator()
        {
                return new School("北京大学");
        }
        
        @Bean(name="myStudent")
        public Student myStudentCreator()
        {
                return new Student("张三",23);
        }
}
  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" 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.xsd"> <!-- bean definitions here -->
        <context:component-scan base-package="com.jd.wang"></context:component-scan>
</beans>
  • 优先级问题
    XMl的优先级要高于注解

猜你喜欢

转载自blog.csdn.net/weixin_42150936/article/details/84954445