Spring框架学习(中)
目录
1. DI注入的几种方式
1.1 Set方法注入
1.2 构造器方法注入
2. spring常用注解
1. 组件扫描与依赖注入
2. 配置相关
3. AOP相关注解
4. 事务管理注解
5. @Configuration注解
6. @Component
7. @Repository
8. @Service
9. @Autowire
10. 测试注解
AAC AnnotationConfigApplicationContext
1. DI注入的几种方式
1.1 Set方法注入
1. service层
package com.v.service;
import com.v.dao.EnrolledDao;
/**
* 假设此类是:
* 实训系统报名类service层的实现类
*/
public class EnrolledServiceImp {
/**
* 假设此方法是报名系统的报名业务逻辑处理方法
* 此方法中需要调用到dao层的报名添加记录方法
*/
EnrolledDao enrolledDao;// 单单从代码层面来看,此时enrolledDao为null,并没有实例化
public void baoming(){
enrolledDao.register();// 调用dao层对报名表添加记录的方法
}/**
* 此方法是我自动生成的,用于使用spring完成set方式注入对象
* @param enrolledDao
*/
public void setEnrolledDao(EnrolledDao enrolledDao) {
this.enrolledDao = enrolledDao;
}
}
2. dao层
package com.v.dao;
/**
* 假设此类是:
* 实训报名类的dao层实现类
*/
public class EnrolledDao {
/**
* 假设此方法是dao层报名方法
* 在此方法里面写对报名表的添加记录操作
* @return
*/
public boolean register(){
// 这里写对报名表的插入操作代码....
System.out.println("报名成功!");
return true;
}
}
我们现在需要在service层的EnrolledServiceImp中,自动创建dao层的EnrolledDao。于是在EnrolledServiceImp,写一个dao的set方法。
3. 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!--把EnrolledServiceImp交给spring管理-->
<bean id="enrolledServiceImp" class="com.frank.service.EnrolledServiceImp"><!--ref是被注入类的 id-->
<property name="enrolledDao" ref="enrolledDao"></property>
</bean><!--把EnrolledDao交给spring管理-->
<bean id="enrolledDao" class="com.frank.dao.EnrolledDao"></bean>
</beans>
4. 测试类
import com.v.service.EnrolledServiceImp;
import org.springframework.context.support.ClassPathXmlApplicationContext;/**
* 此类用于测试说明spring set方式注入对象是否成功
*/
public class TestApp {
public static void main(String[] args) {// 1、因为我要找容器要对象,不是自己手动去new对象,所以先要创建容器对象
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("bean.xml");
// 2、容器对象有了,我怎么拿到我想要的对象呢?通过getbean方法得到,用参数指定要的对象的名字
EnrolledServiceImp enrolledServiceImp = (EnrolledServiceImp) app.getBean("enrolledServiceImp");
// 3、拿到了我想要的对象,为了测试是否成功,我调用一下里面的方法,如果控制台有打印说明成功
enrolledServiceImp.baoming();// baoming方法中调用了dao层的register方法,控制台输出的就是register方法里面打印的代码执行了
}
}
1.2 构造器方法注入
还是以set方式注入的代码为例;使用构造器方式注入的话只需要改变两个地方即可:
一:把set方法改成带参的构造方法;
二:把bean.xml里面的<property>标签换成<constructor-arg>标签
1、 在Service层中
package com.v.service;
import com.v.dao.EnrolledDao;
/**
* 假设此类是:
* 实训系统报名类service层的实现类
*/
public class EnrolledServiceImp {
/**
* 假设此方法是报名系统的报名业务逻辑处理方法
* 此方法中需要调用到dao层的报名添加记录方法
*/
EnrolledDao enrolledDao;// 单单从代码层面来看,此时enrolledDao为null,并没有实例化
public void baoming(){
enrolledDao.register();// 调用dao层对报名表添加记录的方法
}/**
* 此方法是我自动生成的,用于使用spring完成set方式注入对象
* @param enrolledDao
*/
public EnrolledServiceImp (EnrolledDao enrolledDao) {
this.enrolledDao = enrolledDao;
}//无参构造必须要写
public EnrolledServiceImp (){}
}
2、 在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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!--把EnrolledServiceImp交给spring管理-->
<bean id="enrolledServiceImp" class="com.v.service.EnrolledServiceImp"><constructor-arg ref="enrolledDao"/>
</property>
</bean><!--把EnrolledDao交给spring管理-->
<bean id="enrolledDao" class="com.v.EnrolledDao"></bean>
</beans>
2. spring常用注解
spring注解是一个非常非常非常好用的工具,如果你用过一次,你就会彻底的爱上这个注解,这些注解可以让我们不用写xml文件了
1. 组件扫描与依赖注入
@Component
- 通用组件注解,标记类为Spring管理的组件@Repository
- 标记数据访问层(DAO)组件@Service
- 标记业务服务层组件@Controller
- 标记表现层组件(如MVC控制器)@Autowired
- 自动装配依赖@Qualifier
- 与@Autowired
配合使用,指定具体要注入的bean@Resource
- JSR-250提供的依赖注入注解@Inject
- JSR-330提供的依赖注入注解
2. 配置相关
@Configuration
- 标记类为配置类@Bean
- 在配置类中声明一个bean@Import
- 导入其他配置类@ComponentScan
- 配置组件扫描的路径@Profile
- 指定bean在特定环境下激活
3. AOP相关注解
@Aspect
- 声明一个切面类@Pointcut
- 定义切点表达式@Before
,@After
,@Around
,@AfterReturning
,@AfterThrowing
- 定义通知类型
4. 事务管理注解
@Transactional
- 声明事务@EnableTransactionManagement
- 启用注解驱动的事务管理
5. @Configuration注解
将spring.xml文件替换为一个SpringConfig类
每次使用xml文件都要记住一大堆的标签,肯定会觉得很麻烦,虽然写得多了也就习惯了,但是能让代码更简单一点何乐而不为呢
首先,创建一个SpringConfig类,然后在类名上,写一个@Configuration,就结束了
package com.v.config;
import org.springframework.context.annotation.Configuration;
@Configuration
//注解扫描整个包
@ComponentScan("com.v")
public class SpringConfig {
}
这个就相当于spring.xml文件了,@Configuration是声明spring的配置类
6. @Component
可以替代<bean>标签,在需要被spring容器管理的实体类上写入@Component
package com.v.pojo;
import org.springframework.stereotype.Component;
@Componen("student")
public class Student {private String name;private int age;}
7. @Repository
可以替代<bean>标签,在需要被spring容器管理的数据管理层(Dao层)上写入@Repository
package com.v.config.dao;
import org.springframework.stereotype.Repository;
@Repository("studentDao")
public class StudentDao {
}
8. @Service
可以替代<bean>标签,在需要被spring容器管理的业务层(Service层)上写入@Service
@Service("studentService")
public class StudentService {@Autowiredprivate StudentDao studentDao;@Autowiredprivate Student student;
9. @Autowire
可以自动注入到其他类里
@Service("studentService")
public class StudentService {@Autowiredprivate StudentDao studentDao;@Autowiredprivate Student student;
10. 测试注解
我将以完整的代码进行测试,这段代码复制粘贴就能用。
com.v.config包下的spring配置类
package com.v.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.v")
public class SpringConfig {
}
com.v.service包下的业务层
package com.v.service;
import com.v.dao.StudentDao;
import com.v.pojo.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service("studentService")
public class StudentService {@Autowiredprivate StudentDao studentDao;@Autowiredprivate Student student;public Student getStudent() {return student;}public void setStudent(Student student) {this.student = student;}public StudentDao getStudentDao() {return studentDao;}public void setStudentDao(StudentDao studentDao) {this.studentDao = studentDao;}
}
com.v.dao包下的数据持久层
package com.v.dao;
import org.springframework.stereotype.Repository;
@Repository("studentDao")
public class StudentDao {
}
com.v.pojo包下的实体类
package com.v.pojo;
import org.springframework.stereotype.Component;
@Component("student")
public class Student {private Integer id;private String name;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Student{" +"id=" + id +", name='" + name + '\'' +'}';}
}
main方法
import com.v.config.SpringConfig;
import com.v.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {@Autowiredprivate static StudentService studentService;public static void main(String[] args) {//解析SpringConfig类AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);studentService = (StudentService) context.getBean("studentService");System.out.println(studentService.getStudent());}
}
在解析的时候,那个解析类是很长的,我们可以记AAC AnnotationConfigApplicationContext
AAC AnnotationConfigApplicationContext
测试结果:
如果没有解析的话,结果如下
这是经典空指针异常