spring框架:通过注解配置bean,扫描组件的包含和排除,注解的自动装配

注解配置bean

注解配置bean有两个步骤:

  1. 将需要spring管理的对象加上注解
  2. 在spring的配置文件里面加上扫描器
    注解有四种类型:
    注解都是写在实现类里面的,不是写在接口上面
@Component普通组件,就是标识这个类是要给springIOC容器管理的组件
@Repository持久化层组件,就是标识一个持久化层的类要给springIOC容器管理,持久化层就是要进行数据处理的类
@Service业务逻辑层组件,就是标识一个业务逻辑层的类要给springIOC容器管理
@Controller控制层组件,就是标识一个控制层的类要给springIOC容器管理

其实这四种类型的注解都是一个作用的,就是给spring管理对象,只是名字不一样,为什么名字不一样呢?是为了给程序员一个方便的,比如本来不同作用的类,控制层的类就写控制层注解,业务逻辑层的类就写业务逻辑层的注解,这样程序员一看到注解就知道这个类是干嘛用的了
加上注解的类后就相当于在spring的配置文件里面加上了一个< bean>的标签,而标签的id名就是类的名字的首字母小写,它的字母不变所得的id名,class肯定是扫描到的全限名称
配置文件的扫描器
加上context的命名空间后,在里面有个标签
<context:component-scan base-package="user"></context:component-scan>
这个就是spring里面的扫描器,它可以将指定的包里面的类都进行扫描,如果里面有注解就加入spring的管理
例子:

package user;

import org.springframework.stereotype.Controller;

@Controller
public class UserController
{
	public UserController()
	{
		System.out.println("UserController");
	}
}

package user;

public interface UserDao
{

}

package user;

import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImpl implements UserDao
{
	public UserDaoImpl()
	{
		System.out.println("UserDaoImpl");
	}
}

package user;

public interface UserService
{

}

package user;

import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService
{
	public UserServiceImpl()
	{
		System.out.println("UserServiceImpl");
	}
}

<?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">

	<context:component-scan base-package="user"></context:component-scan>
</beans>

package user;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test
{
	public static void main(String[] args)
	{
		ClassPathXmlApplicationContext ac=new ClassPathXmlApplicationContext("user.xml");
		UserController userController = ac.getBean("userController", UserController.class);
		System.out.println(userController);
		ac.close();
	}
}

结果:
信息: Loading XML bean definitions from class path resource [user.xml]
UserController
UserDaoImpl
UserServiceImpl
user.UserController@5b7a5baa
402, 2020 9:56:49 上午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@48cf768c: startup date [Thu Apr 02 09:56:49 CST 2020]; root of context hierarchy

扫描组件的包含和排除

在上面的扫描组件中,如果扫描的包的下面有很多的类或者很多不需要管理的类,但是这个类又有写扫描注释,如果让扫描器全部扫描后加入到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">

	<context:component-scan base-package="user" use-default-filters="false">
		<!-- 这里是根据注解来扫描组件,include就是包含什么组件你需要扫描的,
		type的值时annotation,就是注解的意思,后面的表达式就是注解的权限名
		但是如果想使用下面自己设置的扫描方式,就得将默认的扫描全部的去掉,
		就是将use-default-filters的值改成false:例如use-default-filters="false"
		这样就不是扫描所有的类,而是扫描你include的类
		 -->
		<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
		
		<!-- assignable就是根据类的类型来扫描,后面的表达式就是写需要扫描的类的权限名 -->
		<context:include-filter type="assignable" expression="user.UserServiceImpl"/>
	</context:component-scan>
	
	<context:component-scan base-package="user" use-default-filters="true">
		<!-- 这个是扫描组件的时候不包含什么,这里需要注意的是use-default-filters="true"
		这个要么设置 成true,要么就不设置,因为默认是true,这个为true就是先扫描所有的类
		然后根据自己定义的扫描规则排除一些类
		 -->
		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
		<context:exclude-filter type="assignable" expression="user.UserServiceImpl"/>
	</context:component-scan>
</beans>

注意的是:< context:component-scan >里面要么是一个或多个include,要么是一个或多个exclude,这两个东西不能同时处在,就是不能又包含又排除的

注解的自动装配

package user;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test
{
	public static void main(String[] args)
	{
		ClassPathXmlApplicationContext ac=new ClassPathXmlApplicationContext("user.xml");
		UserController userController = ac.getBean("userController", UserController.class);
		System.out.println(userController);
		ac.close();
		userController.adduser();
	}
}
package user;

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

@Controller
public class UserController
{
	public UserController()
	{
		System.out.println("UserController");
	}
//  之前是这样创建	
//	private UserService userservice=new UserServiceImpl();
	//现在是直接加一个自动装配的注解,spring就会根据类型来自动装配,如果类型装配不成功再根据id进行装配
	@Autowired
	private UserService userservice;
	public void adduser()
	{
		userservice.adduser();
	}
}
package user;

public interface UserService
{
	void adduser();
}

package user;

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

@Service
public class UserServiceImpl implements UserService
{
	public UserServiceImpl()
	{
		System.out.println("UserServiceImpl");
	}
//	之前是这样
//	private UserDao dao=new UserDaoImpl();
	@Autowired
	private UserDao dao;
	
	@Override
	public void adduser()
	{
		dao.adduser();
	}
}

上面的自动装配是根据spring容器里面的类型为当前的注释属性进行赋值的,你认真看就会发现,我创建的名字都是接口的名字,但是spring却是能为它赋值,所以肯定就是根据类型来赋值的.其实呢,@Autowired默认是使用byType的方式装配,此时要求里面只有一个bean能为它赋值,如果byType装配不了,那么就采取byName的方式,要求容器中有一个bean的id和属性名一致
还有可以这样操作

  1. @Autowired是自动为属性找到对应的bean赋值,如果找不到的话就会报错,终止程序运行,如果在找不到的情况下我又不想它报错,就是这个装配不是必须要的,那么就可以在注释后面加参数
    @Autowired(required = false)默认是true,这样就算找不到要装配的bean也不会报错,直接那个属性就是null
  2. 对于注释扫描的组件,默认是扫描后给spring管理,bean的id是类的名字的首字母小写,如果你不想类名首字母,可以在注释后面加上value="beanid"进行设置beanid,例如
@Controller(value = "jane")
public class UserController
如果注释只有一个value的属性,那么可以简写成@Controller("jane"),
如果有多个属性,就必须严格按照(属性名1=属性值1,属性名2=属性值2)这样写
  1. 当@Autowired注解为属性自动装配的时候,这时有多个符合这个属性的bean,但是我们知道我们需要哪一个bean进行装配,那么就可以在@Autowired的下面再写一个注解@Qualifier(value=“beanid”)进行指定某一个bean为属性赋值,比如
	@Autowired(required = false)
	@Qualifier(value = "userservice")
	private UserService userservice;

@Qualifier必须在有@Autowired的前提下使用,@Qualifier的value的值就是需要装配的bean的id
@Autowired(required = false)
@Qualifier(value = “userservice”)
也可以注释在方法上,写在方法上,那么它作用的地方就是方法的参数,比如下面,注解在方法上就是给userservice参数进行装配,和方法名没有关系的

	@Autowired(required = false)
	@Qualifier(value = "userservice")
	public void setUserservice(UserService userservice)
	{
		this.userservice = userservice;
	}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ReflectMirroring

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值