Sprinig注解模式

Spring注解模式

自动装配

说明

  • Spring基于配置文件 为了让属性(对象的引用)注入更加的简单,则推出了自动装配模式
    • 根据名称自动装配
    • 根据类型自动装配

配置规则

<!--构建Service
自动装配:程序无需手动的编辑property属性
autowire="byName" 根据属性的名称进行注入
	1.找到对象的所有的set() setUserDao()
	2.setUserDao ~~~ set去掉 ~~~ UserDao ~~~ 首字母小写 ~~~ userDao属性
	3.Spring会根据对象的属性查找自己维护的Map集合,根据据userDao的名称,查找Map中的Key与之对应,如果匹配成功,则能自动的效用set()实现注入(必须得有set())
autowire="byType" 根据属性的类型进行注入
	1.找到对象的所有的set() setUserDao()
	2.根据set(),找到方法中的参数类型UserDao.class	
	3.Spring根据自己维护的对象的Class进行匹配,如果匹配成功,则实现注入(set())
autowire:规则 如果配置了byName则首先按照name查找,如果查找不到按照byType方式查找
未来,一般首选类型的方式查找-->

<bean id="userController" class="cn.lz.controller.UserController" autowire="byName"></bean>

<bean id="userService" class="cn.lz.service.UserServiceImpl" autowire="byType"></bean>

注解模式

  1. 关于注解的说明:Spring为了简化xml配置方式,研发注解模式。Spring为了程序更加严谨,通过不同的注解标识不同的层级,但是注解的功能相同。

    • @Controller:用来标识Controller层的代码,相当于将对象交给Spring管理
    • @Service:用来表示Service层的代码,相当于将对象交给Spring管理
    • @Repository:用来标识持久层
    • @Component:万用注解
  2. 注解使用的原理

     /**
      * <bean id="类名首字母小写" class="UserDaoImpl.class">
      * 如果需要修改 bean 的 id,则需要手动添加即可
      * 即 @Repository(value = "userDao")
      */
     @Repository
     public class UserDaoImpl implements UserDao {
     	public void addUser(User user) {
     		System.out.println("连接数据库添加用户:" + user);
     	}
     }
    
  3. 编辑配置文件

     <?xml version="1.0" encoding="UTF-8"?>
     <beans xmlns="http://www.springframework.org/schema/beans"
     	   xmlns:context="http://www.springframework.org/schema/context"
     	   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
     							http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
     	<!--构建User对象-->
     	<bean id="user" class="cn.lz.pojo.User">
     		<!--根据name的属性查找对象的setId() 将value当作参数 调用set()完成赋值-->
     		<property name="id" value="100"></property>
     		<property name="name">
     			<value><![CDATA[<武则天>]]></value>
     		</property>
     	</bean>
    
     	<!--让注解生效,开启包扫描
     		包路径特点:给定包路径,则自动扫描同包及子孙包中的类
     		base-package:根据指定的包路径查找注解
     		写方式:多个包路径 使用逗号(,)分隔
     		<context:component-scan base-package="cn.lz.controller,cn.lz.service,cn.lz.dao"></context:component-scan>
     	-->
     	<context:component-scan base-package="cn.lz"></context:component-scan>
     </beans>
    
  4. 属性注解

     /**
      * 关于注解的说明
      * @Autowired 可以根据类型/属性名称进行注入 首先按照类型进行注入,如果类型注入失败,则根据属性名称注入。
      * @Qualifier 如果需要按照名称进行注入,则需要额外添加@Qualifier
      * @Resource (type = "Xxx.class",name = "属性名称")
      * 关于注解补充:由于@Resource注解时由Java原生提供的,不是Spring官方的,所以不建议使用
      */
    
    • 上述的属性的注入在调用是,自动的封装了set(),所以set()可以省略不写

实现MVC的纯注解开发

编辑xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:context="http://www.springframework.org/schema/context"
	   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
							http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

	<!--开启包扫描-->
	<context:component-scan base-package="cn.lz"></context:component-scan>
</beans>

关于注解的说明

  • 注解的作用:程序中某些功能以低耦合的形式进行调用。

  • 元注解:

    • @Target({ElementType.TYPE}) 表示注解对谁有效 type:类,method:方法有效
    • @Retention(RetentionPolicy.RUNTIME) 运行期有效
    • @Documented 该注解注释编译到API文档中
  • 由谁加载:由Spring内部的源码负责调用。

优化xml配置文件

  • 说明:随着软件技术发展,xml配置文件显得臃肿,不便于操作,所以Spring后期提出了配置类的思想,将所有的配置文件中的内容写到Java类中。

  • 编辑配置类:

      @Configuration  // 标识我是一个配置类 相当于application.xml
      //设定包扫描的路径
      //@ComponentScan(value = "cn.lz")
      @ComponentScan("cn.lz")  // 如果注解中只有value属性,value可以省略不写
      public class SpringConfig {
      }
    
  • 编辑测试代码:

      @Test
      public void testAnno(){
      	ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
      	UserController userController = context.getBean(UserController.class);
      	userController.addUser();
      }
    

Spring中常见的问题

  1. 接口多实现类情况说明
    • 原则:Spring规定一个接口最好只有一个实现类
    • 业务需求:要求给UserService提供2个实现类
  2. 案例分析:
    • 编辑实现类A

        @Service("userService")
        public class UserServiceImpl implements UserService {
      
        	@Autowired  //根据类型注入
        //    @Qualifier  //必须按照名称进行匹配 一般不写
        	private UserDao userDao;
      
        	public void addUser(User user) {
        		userDao.addUser(user);
        	}
        }
      
    • 编辑实现类B

        @Service("userServiceB")
        public class UserServiceImplB implements UserService {
        	@Autowired
        	private UserDao userDao;
      
        	public void addUser(User user) {
        		System.out.println("实现类2完成业务调用");
        		userDao.addUser(user);
        	}
        }
      
    • 实现类型的注入

        @Controller
        public class UserController {
        	/**
        	 * @Autowired
        	 * 首先根据属性的类型注入
        	 * 如果类型不匹配,则根据属性的名称进行注入
        	 * 如果添加了@Qualifier
        	 * 则根据属性的名称注入
        	 * 如果名称注入失败,则报错返回
        	 */
        	@Autowired  //自身携带了set()
        	@Qualifier("userServiceB")
        	private UserService userService;
      
        	public void addUser(){
        		User user = new User();
        		user.setId(101);
        		user.setUserName("不知火舞");
        		userService.addUser(user);
        	}
        }
      

Spring注解模式执行的过程

  1. 当程序启动Spring容器时 ApplicationContext 利用beanFactory实例化对象。
  2. 根据配置类中的包扫描开始加载指定的注解(4个),根据配置文件的顺序依次进行加载。
  3. 当程序实例化Controller时,由于确实Service对象,所以挂起线程,继续执行后续逻辑;当构建Service时,由于缺少Dao对象,所以挂起线程,继续执行后续逻辑;当实例化Dao成功时,保存到Spring所维护的Map集合中,执行之前挂起的线程;所以以此类推,所有对象实现封装,最终容器启动成功。
  4. 根据指定的注解注入指定的对象,之后统一交给Spring容器的管理,最终程序启动成功。

Spring容器管理业务数据@Bean注解

  1. @Bean作用:通过该注解可以将业务数据实例化之后,交给Spring容器管理,但是@Bean注解应该写到配置类中。

     @Configuration  // 标识我是一个配置类 相当于application.xml
     //设定包扫描的路径
     //@ComponentScan(value = "cn.lz") // 如果注解中只有value属性 可以省略不写
     @ComponentScan("cn.lz")
     public class SpringConfig {
     	/**
     	 * Spring<bean id="方法的名称" class="返回值的类型" />
     	 * 执行@Bean方法,将方法名称当作id,把返回值的对象直接保存到Map集合中
     	 */
     	@Bean
     	public User user(){
     		User user = new User();
     		user.setId(111);
     		user.setUserName("Spring容器");
     		return user;
     	}
     }
    
  2. 编辑UserController

     @Controller
     public class UserController {
    
     	@Autowired  //自身携带了set()
     	@Qualifier("userServiceB")
     	private UserService userService;
    
     	@Autowired
     	private User user;  //从容器中动态获取
    
     	public void addUser(){
     		userService.addUser(user);
     	}
     }
    

Spring动态获取外部数据

  1. 编辑properties文件
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6VU0VrmD-1626761569344)(Spring注解模式_files/1.jpg)]

     # 规则:properties文件
     # 数据结构类型:k-v结构
     # 存储数据类型:只能保存String类型
     # 加载时的编码格式:加载时默认采用ISO-8859-1格式解析 中文必然乱码
     user.id = 1001
     # Spring容器获取的当前计算机的名称 慎用
     # user.user=Xxx
     user.userName=鲁班七号
    
  2. 编辑配置类

    • @PropertySource
      • 注解用法:@PropertySource(“classpath:/user.properties”)
      • 注解说明:@PropertySource() 作用:加载指定的properties配置文件,将数据保存到容器中
    • @Value
      • 注解用法:@Value(123) 将123的值赋值给id
      • 注解说明:@Value(" u s e r . i d " ) 在 S p r i n g 的容器中查找 k e y = u s e r . i d 的数据,通过 {user.id}") 在Spring的容器中查找key=user.id的数据,通过 user.id")Spring的容器中查找key=user.id的数据,通过{}语法获取
    •   @Configuration  // 标识我是一个配置类 相当于application.xml
        //设定包扫描的路径
        //@ComponentScan(value = "cn.lz") // 如果注解中只有value属性 可以省略不写
        @ComponentScan("cn.lz")
        // @PropertySource() 作用:加载指定的properties配置文件,将数据保存到容器中
        // encoding = "utf-8" 指定字符集的编码格式
        @PropertySource(value = "classpath:/user.properties",encoding = "utf-8")
        public class SpringConfig {
      
        	// 定义对象属性,准备接受数据
        	// @Value(123) 将123的值赋值给id
        	// @Value("${user.id}") 在Spring的容器中查找key=user.id的数据,通过${} 进行触发
        	@Value("${user.id}")
        	private Integer id;
        	@Value("${user.userName}")
        	private String userName;
      
        	/**
        	 * Spring<bean id="方法的名称" class="返回值的类型" />
        	 * 执行@Bean方法,将方法名称当作id,把返回值的对象直接保存到Map集合中
        	 */
        	@Bean
        	public User user(){
        		User user = new User();
        		user.setId(id);
        		user.setUserName(userName);
        		return user;
        	}
        }
      

关于Spring工厂模式说明

Spring源码中创建对象都是采用工厂模式 接口:BeanFactory(顶级接口)

Spring开发中需要手动的创建对象时,一般采用FactoryBean(业务接口

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

刘刘刘刘刘先生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值