Spring框架自学之路(五)

(05Day)

    前面讲的都是如何在spring配置文件中进行配置Bean,接下来我们来看看如何使用Spring注解配置Bean。

    (1)基于注解配置Bean

        我们给一个Bean配置注解的话,那么spring容器是如何知道我这个Bean配置了注解呢?在Spring配置文件中提供了一个<context:component-scan base-package="指定扫描包的路径"></context:component-scan>节点进行组件扫描,它可以扫描你配置的包的路径以及其子包。

        那么都有哪些注解呢?spring提供了以下四种注解:

  1. @Component: 基本注解, 标识了一个受 Spring 管理的组件
  2. @Respository: 标识持久层组件
  3. @Service: 标识服务层(业务层)组件
  4. @Controller: 标识表现层组件

    注意实际上这些注解是可以混用的,也就是说可以用Respository标识服务层。用Service标识表现层。但是建议按照对应的来设置注解。使用注解后其Bean的名字就为类的名字(注:首字母会变为小写)。那么如何使用注解呢?下面我就用一个Service层做一个示例;

package com.annotation.Service;
import org.springframework.stereotype.Service;
//添加注解自动配置后名字类名首字母会变成小写的
@Service
public class UserService {

	public void add(){
		System.out.println("UserService add ...");

	}
}
    在<context:component-scan base-package="指定扫描包的路径">中有一个元素resource-pattern。如果仅希望扫描特定的类而非基包下的所有类就可以使用这个属性进行设置。同时在<context:component-scan base-package="指定扫描包的路径">的子节点下还有context:exclude-filter(除了...外)和context:include-filter(包括....在内)两个节点。这两个节点是用来过滤的。其type属性可以支持多钟类型的过滤表达式,一般只用到anntation和assinable两个。分别表示对某个注解进行过滤和对某个类进行过滤。还有在context:component-scan 的元素中是有默认的拦截栈的(默认拦截四个注解)如果需要把默认拦截栈关了需要设置 use-default-filters 为false。来看个示例:
<?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.0.xsd">

	<!-- 指定IOC容器要扫描的包,会扫描指定的包以及其子包 	-->
	<context:component-scan base-package="com.annotation"></context:component-scan>

	<!-- 如果仅希望扫描特定的类而非基包下的所有类,可使用 resource-pattern 属性过滤特定的类
	<context:component-scan base-package="com.annotation"
	resource-pattern="Controller/*.class"></context:component-scan>
	 -->
	 
	 <!-- 子节点context:exclude-filter 指定排除扫描哪些指定表达式组件
	 <context:component-scan base-package="com.annotation">
	 	<context:exclude-filter type="annotation"
	 	 expression="org.springframework.stereotype.Controller"/>
	 </context:component-scan>
	 -->
	 
	 <!--use-default-filters默认为true 即使用的是默认的filter(四个组件都扫描) 如果false 就为我们子节点设
	 置的filter
	  context:include-filter即扫描指定的表达式组件
	 <context:component-scan 
	 base-package="com.annotation"
	 use-default-filters="false">
	 	<context:include-filter type="annotation"
	 	 expression="org.springframework.stereotype.Controller"/>
	 </context:component-scan>
	 -->
	 <!-- 至于其中的type=annotation是对指定的表达式组件进行扫描,而type=assinable是对指定的类进行扫描 -->
</beans>

    (2)注解来装配 Bean 的属性

        我们知道一般Bean与Bean之间有关联关系,那么这关联关系用注解来配置该怎么搞呢?其实很简单在spring中提供了@Autowired 和 @Resource 、@Inject注解的属性,用来为Bean与Bean之间的关联关系做配置。(这三种配置是相似的,因此一般我们推荐使用@Autowired)

        直接在属性上添加@Autowired就可以为这个Bean自动的装配上。其实@Autowired不仅可以在属性上使用,它还可以在构造方法,普通字段(即使是非 public), 一切具有参数的方法上应用。默认情况下,所有使用 @Authwired 注解的属性都需要被设置. 当 Spring 找不到匹配的 Bean 装配属性时,会抛出异常, 若某一属性允许不被设置,可以设置 @Authwired 注解的 required 属性为 false。当 IOC 容器里存在多个类型兼容的 Bean 时, 通过类型的自动装配将无法工作.。此时可以在 @Qualifier 注解里提供 Bean 的名称。 Spring 允许对方法的入参标注 @Qualifiter 已指定注入 Bean 的名称。@Authwired 注解也可以应用在数组类型的属性上,此时 Spring 将会把所有匹配的 Bean 进行自动装配。@Authwired 注解也可以应用在集合属性上, 此时 Spring 读取该集合的类型信息, 然后自动装配所有与之兼容的 Bean。@Authwired 注解用在 java.util.Map 上时,若该 Map 的键值为 String,那么 Spring 将自动装配与之 Map 值类型兼容的 Bean。此时 Bean 的名称作为键值,Bean做为value值。接下来我们来看一个示例:

    首先我们创建一个TextObject类并不为其添加注解。

package com.annotation;

public class TextObject {

}

    接着我们分别创建Controll,Service,Respository,类。在Controll中调用Service,在Service中调用Respository。同时Respository为一个接口UserRespositoryImpl和UserRespositoryJdbc为实现该接口的类,这两个类用来测试@Qualifiter注解。

package com.annotation.Controller;

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

import com.annotation.TextObject;
import com.annotation.Service.UserService;

@Controller
public class UserController {
	//Autowired 注解自动装配具有兼容类型的单个 Bean属性。构造器, 普通字段(即使是非 public), 一切具有参数的方法都可以应用。
	@Autowired
	private UserService userservice;
	/*默认情况下, 所有使用 @Authwired 注解的属性都需要被设置. 当 Spring 找不到匹配的 Bean
	 装配属性时, 会抛出异常, 若某一属性允许不被设置,可以设置 @Authwired 注解的 required 属性为
	  false*/
	@Autowired(required=false)
	private TextObject textObject;
	public void excute(){
		System.out.println("UserController excute....");
		userservice.add();
		System.out.println(textObject);
	}
}
package com.annotation.Service;

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

import com.annotation.Respository.UserRespository;
//添加注解自动配置后名字类名首字母会变成小写的
@Service
public class UserService {
	/*默认情况下, 当 IOC 容器里存在多个类型兼容的 Bean 时, 通过类型的自动装配将无法工作. 
	 * 此时Qualifiter 已指定注入 Bean 的名称 注意首字母要改成小写。同时也可以把@Qualifier
	 * 写到方法参数前 
	 * @Autowired
	public void setUserrespository(@Qualifier("userRespositoryImpl")UserRespository userrespository) {
		this.userrespository = userrespository;
	}*/
	
	@Autowired
	@Qualifier("userRespositoryImpl")
	private UserRespository userrespository;
	
	public void add(){
		System.out.println("UserService add ...");
		userrespository.say();
	}
}

package com.annotation.Respository;

public interface UserRespository {
	public void say();
}
package com.annotation.Respository;

import org.springframework.stereotype.Repository;

@Repository()
public class UserRespositoryImpl implements UserRespository {

	public void say() {
		System.out.println("UserRespository say......");
	}

}
package com.annotation.Respository;

import org.springframework.stereotype.Repository;

@Repository
public class UserRespositoryJdbc implements UserRespository {

	public void say() {
		System.out.println("UserRespositoryJdbc say....");
	}

}

    最后在spring中配置扫描路径,并且写一个测试类。

<?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.0.xsd">

	<!-- 指定IOC容器要扫描的包,会扫描指定的包以及其子包 	-->
	<context:component-scan base-package="com.annotation"></context:component-scan>

	
</beans>
package com.annotation;

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

import com.annotation.Controller.UserController;

public class Main12 {

	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml");

		UserController usercontroller = (UserController) ctx.getBean("userController");
		System.out.println(usercontroller);
		usercontroller.excute();

	}

}

    (3)泛型依赖注入

        什么是泛型依赖注入呢?泛型依赖注入是在spring4.0中加入的。那么该怎么理解呢?比如说我们有一个BaseService<T>和BaseRepository<T>。然后这两个类之间有引用关系,也就是说在BaseService里有一个成员变量是BaseRepository类型的。这两个类可能会有很多实现类比。如说BaseService有一个实现类叫做UserService在继承父类BaseService的时候要提供泛型T,比如说泛型T是User。BaseRepository也一样,有个子类叫做UserRepository在继承的时候也提供了泛型T是User。那么这个时候UserService和UserRepository之间会自动的建立引用关系,这就是所谓的泛型依赖注入。OK我们通过代码来看下

        首先分别创建两个Base类

package com.generic.di;

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

public class BaseService<T> {
	@Autowired
	protected BaseRepository<T> repository;
	public void add(){
		System.out.println("add.....");
		System.out.println(repository);
	}
}
package com.generic.di;

public class BaseRepository<T> {

}
    然后创建两个User子类并创建一个User(随意一个User类省略)

package com.generic.di;

import org.springframework.stereotype.Service;

@Service
public class UserService extends BaseService<User>{

}
package com.generic.di;

import org.springframework.stereotype.Repository;

@Repository
public class UserRepository extends BaseRepository<User>{

}

    最后做个测试,发现可以正常输出。这就是泛型依赖注入。

package com.generic.di;

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

public class Main13 {

	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-generic-di.xml");
		UserService userService = (UserService) ctx.getBean("userService");
		userService.add();
	}

}





    

猜你喜欢

转载自blog.csdn.net/qq_38166944/article/details/79833601