一、基于注解的IOC配置
1、导入xmlns:cont
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.my"></context:component-scan>
</bean
2、用于创建对象的注解
2.1、@Bean
a、Spring的@Bean注解用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。产生这个Bean对象的方法Spring只会调用一次,随后这个Spring将会将这个Bean对象放在自己的IOC容器中。
b、SpringIOC 容器管理一个或者多个bean,这些bean都需要在@Configuration注解下进行创建,在一个方法上使用@Bean注解就表明这个方法需要交给Spring进行管理。
2.2、@Component
a、属性:
value----用于指定bean的id,默认为当前类名(首字母小写)
如:@Component(“id值”)
b、衍生注解:同Component作用和属性相同,用于方便分层
@Controller—用于表现层
@Service—用于服务层
@Repository—用于持久层
3、用于注入数据的注解
@Autowired、@Inject、@Resource一般情况通用,可注解在set方法或属性上
同相同
A、@Autowired—自动按照类型注入。只要容器中有唯一的bean类型与要注入的变量类型匹配,就能注入
1、出现位置:变量上或方法上
2、细节:不需要set方法
3、注入问题
a、没有匹配类型的bean—报错
b、多个相同类型的bean—bean的id和要注入的变量名相同则注入此bean否则报错
B、@Qualifier:
作用:在按照类注入的基础上(所以必须和Autowired配合使用—指定bean的id)再按照名称注入。它在给类成员注入时不能单独使用。但是在给方法参数注入时可以,直接指定对应bean的id
C、Resource(name=“bean的id”):
作用:@Autowired+@Qualifier
D、@Value—用于注入基本类型和String类型的数据–也可以获取配置文件中的值application.yml
属性值:用于指定数据的值,可以使用SpEL—Spring的el表达书
4、用于改变作用范围的注解
同中的scope属性相同
注解在相应的Bean @Component上
@Scope — 指定范围取值
singleton:一个人Spring容器只有一个Bean的实例
prototype:每次调用新建一个Bean实例
Request:Web项目中,给每一个http request新建一个Bean实例
Session:Web项目中,给每一个http session新建一个Bean实例
5、和生命周期相关的注解
同中的init-method和destory-method相同
@PreDestory—指定销毁方法
@PostConstruct—指定初始化方法
6、示例
public class TestMain {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("bean.xml");
B b = (B) app.getBean("b");
System.out.println("修改前的b==>"+b.getTestStr());
b.setTestStr("abcdef");
B b2 = (B) app.getBean("b");
//b2值同b,说明只有一个对象(单例) ---@Scope为prototype时,会重新创建对象,并多调用一次初始化
System.out.println("修改后的b==>"+b2.getTestStr());
b.useA();
}
}
//注入容器
@Component
class A {
public void say() {
System.out.println("a注入,执行a方法!");
}
}
//单例注解
@Scope(value = "singleton")
@Component
class B {
//初始化时调用
@PostConstruct
public void initB() {
System.out.println("B初始化了!");
}
//销毁时调用
@PreDestroy
public void desB() {
System.out.println("B被销毁了!");
}
//注入
@Autowired
private A a;
public void useA() {
a.say();
}
//实现set/get方法--用于@Scope测试
private String testStr;
public void setTestStr(String testStr) {
this.testStr = testStr;
}
public String getTestStr() {
return this.testStr;
}
}
二、Spring新注解
1、@Configuration—指定当前类是一个配置类,启到Bean.xml的作用
获取容器方式:ApplicationContext app = new AnnotationConfigApplicationContext(工具类名.class//可加入多个配置类)
public class TestMain {
public static void main(String[] args) {
ApplicationContext app = new AnnotationConfigApplicationContext(TestConf.class);
A a = (A) app.getBean("a");
}
}
@Configuration
class TestConf {
public TestConf() {
System.out.println("配置类初始化");
}
@Bean
@Scope("prototype")
public A a() {
return new A();
}
}
class A{
@PostConstruct
public void initA() {
System.out.println("A初始化!");
}
}
2、@ComponentScan(basePackages=“”/value)—用于通过注解指定spring在创建容器时要扫描的包
扫描包名下所有使用@Service、@Component、@Repository、@Controller注解的类,并注册为bean,为空时默认为当前包下
public class TestMain {
public static void main(String[] args) {
ApplicationContext app = new AnnotationConfigApplicationContext(TestConf.class);
A a = (A) app.getBean("a");
}
}
@Configuration
@ComponentScan
class TestConf {
public TestConf() {
System.out.println("配置类初始化");
}
}
@Component
class A{
@PostConstruct
public void initA() {
System.out.println("A初始化!");
}
}
3、@Bean—用于把当前方法的返回值作为bean对象存入spring的ioc容器中
属性:
name:指定Bean的id—默认值为当前方法名称
细节:
当使用注解配置时,如果方法有参数,spring框架会去容器中查找有没有bean的id和方法参数先类后名相同
public class TestMain {
public static void main(String[] args) {
ApplicationContext app = new AnnotationConfigApplicationContext(TestConf.class);
C c = (C) app.getBean("c");
c.say();
}
}
@Configuration
@ComponentScan
class TestConf {
public TestConf() {
System.out.println("配置类初始化");
}
}
@Component
class A{
@PostConstruct
public void initA() {
System.out.println("A初始化!");
}
//在此注入容器,自动扫描参数名为b的bean并注入方法种
@Bean
public C c(B b) {
return new C(b);
}
}
@Component
class B{
public String str = "B的属性";
}
//不加注解,不注入容器
class C{
private B b;
C(B b){
this.b = b;
}
public void say() {
System.out.println(b.str);
}
}
4、 @Import—用于导入其他类 value用于指定其他配置类的.class文件,多个类用{a.class,b.class…}
@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
public class TestMain {
public static void main(String[] args) {
ApplicationContext app = new AnnotationConfigApplicationContext(TestConf.class);
//@Import导入的为全类名
C c = (C) app.getBean("com.my.test.C");
c.say();
}
}
@Configuration
@ComponentScan
class TestConf {
public TestConf() {
System.out.println("配置类初始化");
}
}
@Component
//使用@Import直接导入C
@Import({C.class})
class A{
@PostConstruct
public void initA() {
System.out.println("A初始化!");
}
}
@Component
class B{
public String str = "B的属性";
}
//不加注解,不注入容器
class C{
private B b;
C(B b){
this.b = b;
}
public void say() {
System.out.println(b.str);
}
}
5、@PropertySource—指定properties文件的位置
6、Spring整合Junit
准备:
1、应用程序的入口
main方法
2、junit单元测试中,没有main方法也能执行
junit集成了一个main方法
该方法就会判断当前测试类中哪些方法有@Test注解
junit就让有Test注解的方法执行
3、junit不会管我们是否采用spring框架
在执行测试方法时,junit根本不知道我们是不是使用了spring框架
所以也就不会为我们读取配置文件/配置类创建srping核心容器
4、由以上三点可知
当测试方法执行时,没有Ioc容器,就算写了Autowired注解,也无法实现注入
步骤:
1、导入jar包spring-test(要和Junit包版本相对应)手动引入:
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
2、使用Junit提供的一个注解把原有的main方法(test)替换成spring提供的
3、告知spring的运行器,spring的ioc创建是基于xml还是注解的,并说明位置
@ContextConfiguration
属性:
locations:指定xml文件的位置,加classpat关键字
classes:指定注解类的位置
4、当使用spring 5版本的时候,要求junit的jar包必须是4.1.2及以上
5、在需要测试的方法上添加@Test,并且,上述两个注解都注解在类上
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class SpringNewAnno {
@Test
public void useSpringTestAnno() {
ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class);
@SuppressWarnings("unchecked")
List<ClassInfo> list = (List<ClassInfo>) app.getBean("classInfoList");
System.out.println(list);
}
}