1.看图
2.业务层接口IAccountService
package com.itheima.service; public interface IAccountService { void saveAccount(); }
3.IAccountServiceImp业务层实现类(里面包含着Resource注入的bean实例,代替持久层的调用)
package com.itheima.service.lmp; import com.itheima.dao.IAccountDao; import com.itheima.dao.Imp.IAccountDaoImp; import com.itheima.service.IAccountService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.ImportResource; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import javax.annotation.Resource; /* 曾经的xml配置: <bean id="accountService" class="com.itheima.service.lmp.IAccountServiceImp" scope=" " init-method=" " destroy-method=" "> <property name=" " value = " " | ref=" "></property> </bean> 1.之前讲了四种: 用于创建对象的 他们的作用就和在xml配置文件中编写一个<bean>标签实现的功能是一样 @component: 作用:用于把当前类对象存入spring容器中(spring是一个mapping值【有key和value】) 属性: value: 用于指定bean的id。当我们不写时,它默认值是当前类名,且首字母小写 @Controller:一般用于表现层 @Service:一般用在持久层 @Repository:一般用在持久层 以上他们三个注解的作用和属性与Component是一模一样的 只是他们三个是spring框架为我们提供明确的三层使用注解: 使我们的三层对象更加清晰 所以说,不属于三层中的任何一层使用的@Component 用于注入数据的(普通/set) 他们的作用就和在xml配置文件中的bean标签中写入一个<property>标签的作用一个 Autowired: 作用:自动按照类型注入。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功 如果ioc容器中没有任何bean的类型和要注入的变量类型匹配,则报错 出现位置: 可以是变量上,也可以是方法上(一般用于方法和类上) Qualifier:(指定名称注入) 作用:按照类中注入的基础上再按名称注入。它在给类成员注入时不能单独使用。但是在给方法参数注入时可以(稍后讲) 属性: value:用于指定注入的bean的id。 Resource:(取代Autowired和Qualifier配合) 作用:直接按照bean的id注入。它可以独立使用 属性: name 用于指定bean的id 额。。。,那为什么不直接用resource,浪费时间????? 总结一下:以上上个注入都只能注入其他的bean类型的数据,而基本类型和String类型无法使用上述的注解实现 另外,集合类型的注入只能通过Xml来实现。 --------------------------------基本数据类型和String类型的注解-------------------------------------- Value 作用:用于注入基本数据类型和String类型的数据 属性: value:用于指定数据的值。它可以使用spring中的SpEl表达式(也就是spring的el表达式) SpEL的写法:${表达式}【区分是哪的表达式,那就看表达式出现在哪个位置】 ------------------------------------------- 用于改变作用范围的 他们的作用就和在bean标签中使用的scope属性实现的功能是一样的 Scope 作用:用于指定的bean的作用范围 属性:Value("值") value:指定范围的取值。常用取值:singleton prototype 了解: 和生命周期相关的 他们的作用就和在bean标签中使用init-method和destroy-method的作用是一样的 PreDestroy 指定销毁方法 PostConstruct 初始化方法 ------写案例去咯!!!!!! */ //@Component(value = "accountService")==》不使用默认id【有两个value也必须得写】 //@Component("accountService")==》默认value也可以 //@Component @Service("accountService") //@Service public class IAccountServiceImp implements IAccountService { //业务层调用——持久层——调用控制层 //有匹配到的就行,匹配到IAccountDao有,就创建accountDao //@Autowired //@Qualifier("accountDao1") //解锁新技能:在@Autowired类型的基础上,按名称注入@Qualifier("变量名称") //解决当时如果不能后台修改的毛病,直接选就行,并且他们两个是配合使用的,当出现多个同类型的对象时 //取代上面两个家伙(配合使用的家伙) @Resource(name = "accountDao") private IAccountDao accountDao;// 这个对象由于是null,于是出现了空指针异常:解决办法:加入Autowired //有两个类型一样的,那就按名称 accuntDao1/accountDao2就可以找到 public void saveAccount() { accountDao.saveAccount(); } }
4.IAccountDao持久层接口
package com.itheima.dao; public interface IAccountDao { void saveAccount(); }
5.实现类1 IAccountDaoImp
package com.itheima.dao.Imp; import com.itheima.dao.IAccountDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; /* * <bean id="accountDao" class="com.itheima.dao.Imp.IAccountDaoImp"></bean> * */ @Repository("accountDao1")/*默认值是什么:首字母大写,小写的类名?*/ //@Repository public class IAccountDaoImp implements IAccountDao { public void saveAccount() { System.out.println("保存了账户11111111111"); } }
5-1.实现类2
package com.itheima.dao.Imp; import com.itheima.dao.IAccountDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; /* * <bean id="accountDao" class="com.itheima.dao.Imp.IAccountDaoImp"></bean> * */ //@Repository("accountDao")/*默认值是什么:首字母大写,小写的类名?*/ @Repository("accountDao2") public class IAccountDaoImp2 implements IAccountDao { public void saveAccount() { System.out.println("保存了账户2222222222222"); } }
6.依赖写入pom.xm
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency> <!-- 添加resource注解依赖 --> <dependency> <groupId>javax.annotation</groupId> <artifactId>jsr250-api</artifactId> <version>1.0</version> </dependency>
7.配置文件bean.xml(管理bean的调度分配)
<?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-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd" > <!-- 告知spring在创建容器时要扫描包(他就会扫描这个包里面的注解,通过对应机制), 配置所需要的标签不是在beans约束,而是一个名称为context名称空间和约束中(导入:声明也要加、约束也要加) 解释: 1. 当你把注解写在实现类中的时候,例如@component,它是通过类创建对象的,然后放入到spring容器中 但是呢!他不知道哪个类需要用的哪个注解,所以他需要扫描包,把它们都找出来,通知一波,哎我找到你, 此时注解的功能得到调用(这里使用的广播机制),而原来的spring容器的配置机制变成了广播扫描机制。 --> <context:component-scan base-package="com.itheima"></context:component-scan> </beans>
8.表现类Client
package com.itheima.ui; import com.itheima.dao.IAccountDao; import com.itheima.dao.Imp.IAccountDaoImp; import com.itheima.service.IAccountService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; //模拟一个表现层,用于调用业务层 public class Client { public static void main(String[] args) { //核心容器获取对象ac ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); //第一种:普通的xml配置id,通过实现类来创建id中的名称来作为对象【<bean id="accountService" class="com.itheima.service.lmp.IAccountServiceImp"/>】 // IAccountService as = (IAccountService) ac.getBean("accountService[指定id]"); //第二种:这里使用的是@Component注解:id的名称默认是类名【那@Component(value也可以指定id名的,不使用类名自己定义也可【value就可以】)】 IAccountService as = (IAccountService) ac.getBean("accountService"); // System.out.println(as); // IAccountDao ado = ac.getBean("IAccountDaoImp", IAccountDao.class); // System.out.println(ado); as.saveAccount(); } } /* *dao: Client调用IAccountServiceImp调用IAccountDaoImp(创建实例化对象的时候) * service:业务返回:IAccountDao ——>IAccountService——>显示Client */ /*IAccountService as = new IAccountServiceImp();普通用法:独立就用spring容器*/
9.注解机制
(1)类级别的注解:如@Component、@Repository、@Controller、@Service注解,都是添加在类上面的类级别注解。
Spring容器根据注解的过滤规则扫描读取注解Bean定义类,并将其注册到Spring IoC容器中。
(2)类内部的注解:如@Autowire、@Value、@Resource以及EJB和WebService相关的注解等,都是添加在类内部的字段或者方法上的类内部注解。
SpringIoC容器通过Bean后置注解处理器解析Bean内部的注解。