您的位置:首页 > 编程语言 > Java开发

Spring和SSM整合中: context-component和context:annotation-config标签的使用

2018-03-26 08:58 686 查看
复习Spring, 正好这两个标签我分的也不是很清, 就写篇文章记录一下.
准备工作:



1.TestController.java:public class TestController {
public void test() {
System.out.println("controller ok");
}
}2.TestService.java:public class TestService {
TestDao testDao;

public void setTestDao(TestDao testDao) {
this.testDao = testDao;
}

public void test() {
System.out.println("service ok");
testDao.test();
}
}3.TestDao.java:public class TestDao {
public void test() {
System.out.println("dao ok");
}
}4.Test.java:public class Test {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
TestController controller = (TestController) context.getBean("testController");
controller.test();

TestService service = (TestService) context.getBean("testService");
service.test();

TestDao testDao = (TestDao) context.getBean("testDao");
testDao.test();
}
}
5.applicationContext.xml<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<bean id="testController" class="com.ld.controller.TestController"></bean>

<bean id="testService" class="com.ld.service.TestService">
<property name="testDao" ref="testDao"/>
</bean>
<bean id="testDao" class="com.ld.dao.TestDao"></bean></beans>---------------------------------------------  假装是条分割线  ---------------------------------------------------------
● 我在配置文件中配置了3个bean,并且为TestService注入了testDao属性.
此时Test类的main方法可以正常运行,不会报错, 结果如下:controller ok
service ok
dao ok
dao ok● 若我想使用@Autowired注解将TestDao注入到TestService中, 则需要context:annotation-config这个标签来启用注解功能.
修改TestService类和配置文件:<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:annotation-config></context:annotation-config>

<bean id="testController" class="com.ld.controller.TestController"></bean>

<bean id="testService" class="com.ld.service.TestService"></bean>

<bean id="testDao" class="com.ld.dao.TestDao"></bean>

</beans>TestService.java:public class TestService {
@Autowired
TestDao testDao;

public void test() {
System.out.println("service ok");
testDao.test();
}
}运行Test的main方法, 结果不变:
controller ok
service ok
dao ok
dao ok● 若我想自动注册bean,而不是在xml文件中使用bean标签来注册, 首先想到的是在被注册类上使用@Component注解,但这里模拟了controller层,service层和dao层, 所以分别使用@Controller, @Service, @Repository注解:
配置文件修改为:<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:annotation-config></context:annotation-config>

</beans>TestController.java:
@Controller
public class TestController {
public void test() {
System.out.println("controller ok");
}
}TestService.java:@Service
public class TestService {
@Autowired
TestDao testDao;

public void test() {
System.out.println("service ok");
testDao.test();
}
}TestDao.java:@Repository
public class TestDao {
public void test() {
System.out.println("dao ok");
}
}现在运行一下,会发现报错了:Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'testController' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1168)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:281)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:956)
at com.ld.test.Test.main(Test.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)根据描述,报错信息为没有名为:"testController"的bean被定义, 其实包括service和dao的bean都没有被定义,只不过我们先调用了testController的test方法,所以在找不到testController后程序就终止了,所以没有打印出相应的错误信息.
● 那为什么会出现这样的异常呢? 我们明明启用了注解功能啊.
原来context:annotation-config标签的作用是只在开始了已被注册的bean上的注解功能, 也就是说之所以我们使用@Autowired注解能将testDao成功注入,是因为我们在配置文件中已经使用bean标签注册了那3个bean. 遇到未注册的bean上的注解,这个标签也无能为力, 它不能将标注了@Component,@Controller等注解的类注册为bean.
那该怎么办呢? 这是时候就该使用context:component-scan标签了.

● context:component-scan标签不仅可以识别@Autowired等注解, 还能将被@Component等注解标注的类注册到Spring的IOC容器中, 成为可供使用的bean.   该标签有一个base-package属性, 用来指定要扫描的包的包名.

修改配置文件:
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:component-scan base-package="com.ld"></context:component-scan>

</beans>


运行结果:
controller ok
service ok
dao ok
dao ok

结果正确.

在SSM整合中的使用



大家都知道Spring和SpringMVC一起使用时, Spring容器包含了SpringMVC容器, 可称为Spring容器为父容器,SpringMVC容器为子容器. 

   我们在applicationContext.xml(SSM整合后一般叫做spring-mybatis.xml)中使用context:component-scan标签, base-package应该指定为除controller包以外的包,因为这样就不会把Controller也注册到Spring容器中. 我们通常会在spring-mvc.xml中也配置一个context:component-scan标签, base-package只指定为controller包,  只将controller注册到SpringMVC容器中. 
● 想了解上述细节请看这篇文章:  https://blog.csdn.net/s740556472/article/details/54879954

那么问题来了, 在spring的配置文件中,base-package该怎么配置呢? 难道要service,dao等包各对应一个context:component-scan标签吗?  这会显得配置文件非常臃肿. Spring当然考虑到了这一点, 提供了它的子标签:<context:include-filter/>和<context:exclude-filte
a548
r/>, 顾名思义, 就是引入过滤器和排除过滤器.使用如下:
<context:component-scan base-package="com.ld">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>



在spring的配置文件中, 只需要使用exclude-filter标签, 将过滤类型设置为annotation(注解), 将expression配置为Controller注解的全名即可实现过滤.

在使用<context:include-filter/>标签时需要注意, 如果你只想扫描几个包,剩下的过滤掉,这样写是不行的:
<context:component-scan base-package="com.ld">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Service" />
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Repository" />
</context:component-scan>

尽管你使用了两个include-filter标签, 但实际上还是将"com.ld"下所有的包扫描了, 这时候需要指定context:component标签的另一个属性: use-default-filter, 将其指定为false即可.
● 具体解析请看这篇文章: https://blog.csdn.net/m0_37965853/article/details/72898490


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐