Spring与IoC

对IoC的理解

IoC,Inversion of Control,控制反转。将原本由代码操纵的对象操控权,交由第三方容器,即反转给了第三方容器。这种对象的依赖关系管理方式,称为IoC。

IoC是一种思想,是一个概念。其实现方式很多,较著名的有两种:

DL:Dependency Lookup,依赖查找。其典型应用是JNDI。Java Naming and Directory Interface,Java名称与服务接口。其实JNDI,就是一个第三的容器。

DI:Dependency Injection,依赖注入。是目前最优秀的解耦方式。其典型应用是Spring。


1.Bean的装配(Bean必须有无参构造器)

  • bean的装配一般用class属性直接指定该Bean的类名,spring通过反射创建该实例,我们还可以使用Bean工厂进行装配
  • 动态工厂Bean的装配:
  • 首先我们定义一个工厂类,里边定义一个方法,用来返回一个对象的实例
  • 在容器中注册工厂Bean并使用动态工厂方式装配该Bean
  • 静态工厂对Bean的装配:
  • 该方式不用注册工厂Bean,但在注册car时需要将class属性指定为静态工厂的类全名

2.Bean的作用范围

  • 单例模式
  • 原型模式(多例)

3.Bean后处理器

  • 如果在Bean初始化的前后需要完成一些工作可以使用Bean后处理器
  • 该处理器会在容器中每一个Bean初始化前后调用
  • 其方法参数为当前Bean
  • 应用场景:
  • 可以使用动态代理对Bean中的方法进行增强
  • 示例代码

 

public class MyBeanPostProcessor implements BeanPostProcessor{

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("postProcessBeforeInitialization执行");
        return bean;//把执行before后的bean返回
    }

    @Override
    public Object postProcessAfterInitialization(final Object bean, String beanName)
            throws BeansException {
        //增强bean
        Object proxy = Proxy.newProxyInstance(
                    bean.getClass().getClassLoader(),
                    bean.getClass().getInterfaces(), 
                    new InvocationHandler() {

                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args)
                                throws Throwable {
                            Object result = method.invoke(bean, args);
                            if(result!=null){
                                result = ((String) result).toUpperCase();
                            }
                            return result;
                        }
                    }
                    );
        System.out.println("postProcessAfterInitialization执行");
        return proxy;//把增强的代理类返回
    }

}

3.DI(依赖注入,即为属性赋值)

1.基于XML的DI

注入的分类:

  • 设值注入:使用该方式注入,bean需要有对应的set方法,其原理就是调用bean的set方法为bean的属性赋值 (常用方式)
<bean id="student" class="com.lscw.beans.Student">
		<property name="name" value="张三" />
		<property name="age" value="23" />
</bean>
  • 构造注入:使用bean的构造器对bean的属性进行注入,完成初始化操作
<bean id="student" class="com.lscw.beans.Student" >
		<constructor-arg name="name" value="张三" />
		<constructor-arg name="age" value="23" />
</bean>
  • p命名空间注入:该方式的注入需要引入约束xmlns:p="http://www.springframework.org/schema/p" 使用方式:p:属性名=“属性值”,p:属性名-ref=“bean名称” (不常用)
<bean id="student" class="com.lscw.beans.Student" p:name="张三" p:age="18" />
  • c命名空间注入:该方式注入bean需要有对应参数的构造器,需要引入约束xmlns:c="http://www.springframework.org/schema/c"(不常用)
<bean id="student1" class="com.lscw.beans.Student" c:name="李四" c:age="24"/>
  • 数组与集合属性的注入
  • 域属性的自动注入:域属性也就是对对象的引用
public class Student {
	private String name;
	private int age;
	private School school;//域属性
}
  • 域属性自动注入的三种方式
  • 通过set方法注入
<bean id="school" class="com.lscw.beans.School">
		<property name="address" value="浙江省杭州市" />
	</bean>
	
	<bean id="student" class="com.lscw.beans.Student">
		<property name="name" value="张三" />
		<property name="age" value="23" />
		<property name="school" ref="school" />
</bean>
  • 域属性的自动注入,ByName方式,容器查找与域属性名称一致的Bean(该bean的id应与属性名一致)
<bean id="student" class="com.lscw.beans.Student" autowire="byName" >
		<property name="name" value="张三" />
		<property name="age" value="23" />
</bean>
  • 域属性的自动注入,ByType方式,容器自动查找与域属性同类型的Bean进行注入,但是容器中不能出现多个同类型的Bean
<bean id="student" class="com.lscw.beans.Student" autowire="byType" >
		<property name="name" value="张三" />
		<property name="age" value="23" />
</bean>
  • SPEL注入:SPEL是spring的表达式,使用方式#{Bean名称.Bean属性名} 注:Bean中必须有get方法
  • 内部Bean的注入
<bean id="student" class="com.lscw.beans.Student">
		<property name="name" value="张三" />
		<property name="age" value="23" />
		<property name="school">
		    <bean class="com.lscw.beans.School">
		        <property name="address" value="浙江省杭州市" />
	        </bean>
		</property>
</bean>
  • 抽象Bean的注入的应用场景:如果多个Bean都需要注入相同的属性,会使Spring的配置文件显得很庞大,并且出现数据冗余的情况,可以使用抽象Bean的注入,定义一个Bean 添加abstract=“true” 属性,则容器初始化时不会创建该Bean。(举个例子,有10个Student对象,这10个student都住在同一个宿舍区,都在同一个班级,对这些学生进行注入时,显然宿舍区和班级都是重复出现的,这时可以注册一个student并添加abstract属性,让其他的学生bean来继承该bean)
  • 同类抽象Bean:该抽象Bean与被注入属性的Bean为同一类型
  • 异类抽象Bean:该Bean不添加class属性,但是有公用的属性用来被继承
<bean id="base" abstract="true">
		<property name="address" value="蓝田4栋"/>
		<property name="className" value="高分子1班"/>
</bean>

2.基于注解的DI

  • 首先我们要导入Spring-aop的jar包
  • 在配置文件中添加context的xsd约束
  • 注册组件扫描器
  • 基本注解:@C omponent(“BeanId”)可选属性,可以指定Bean的id
  • @Service 一般用于Service类上

    @Repository 一般用于Dao类上

    @Controller 一般用于SpringMVC中的处理器上

    以上三个和@Component功能相同但意义不同

  • @Value(属性值)该注解作用在属性上,相当于<property name="xxx" value="xxx"/>

  • 域属性的自动注入@AutoWired 该注解使用ByType注入

  • @AutoWired与@Qualifer结合使用便是ByName方式的注入

  • @Resource默认使用ByType

  • @Resource(name=“xxx”)使用ByName方式注入

  • 其他注解:

  • @Scope表示Bean的作用范围 @Scope(“singleton”) 单例 @Scope(“prototype”) 原型模式 该注解作用在类上

  • @AfterInit 作用于方法上 该方法会在Bean初始化以后执行

  • @PreDestroy 该注解作用于方法上该方法会在Bean销毁前执行(spring容器关闭前)执行

  • 使用XML装配的优先级比使用注解的优先级高

  • 注解使用案例

 

@Component("student")
@Scope("prototype")
public class Student {
	@Value("zs")
	private String name;
	@Value("23")
	private int age;
	@Autowired
	private School school;

	public School getSchool() {
		return school;
	}
	public void setSchool(School school) {
		this.school = school;
	}
	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 Student() {
		super();
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", school=" + school + "]";
	}
	
}	

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值