今天两部分内容,第一部分是注解,使用注解配置Spring,然后第二个是Spring中的AOP,今天就需要这两部分,也没有练习,第一个注解配置Spring,这三大框架都是用注解来配置,这三大框架,都是支持用注解配置的,那么三大框架的出现都是在JAVA1.5以前的,这样1.5推出之后,只要有一个框架用了注解,这两个框架不好意思不用,实际上这三个框架都支持使用注解了,但是Hibernate,还有咱们的Struts,咋没说注解的事呢,那是因为,在企业开发当中,很少在hibernate和struts中用注解来开发,因为struts和hibernate用注解开发的话,导致咱们的类写的乱七八糟的,而至于这个注解,使用最多的框架,那就是Spring,所以Spring这里面,是要讲注解配置的,需要大家学习一下的,那第一个看下注解配置Spring,这个知识点也没啥技术含量,看一下今天有哪些注解,代替昨天哪些配置文件就完事了,讲起来还是比较简单的,注解代替配置文件的,昨天写的那些配置,都可以不用,然后用注解来代替,是这么点事,那咱们先做点准备工作,创建一个项目,spring_day02,然后准备工作第一导包,直接把这6个包加进来

第一步导包就完事了,第二步咱们准备对象,对象,咱们看有没有现成的对象用,就用昨天现成的对象,昨天的对象很典型
package com.learn.bean;/*** @author Leon.Sun*/
public class User {public User() {System.out.println("User空参构造方法");}private String name;private Integer age;private Car car;public User(String name, Car car) {System.out.println("User(String name, Car car)");this.name = name;this.car = car;}public User(Car car, String name) {System.out.println("User(Car car, String name)");this.name = name;this.car = car;}public User(Integer name, Car car) {System.out.println("User(Integer name, Car car)");this.name = name + "";this.car = car;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public void init() {System.out.println("我是初始化方法!");}public void destory() {System.out.println("我是销毁方法!");}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
package com.learn.bean;public class Car {private String name;private String color;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}@Overridepublic String toString() {return "Car [name=" + name + ", color=" + color + "]";}}
再把咱们的配置文件拿过来,接下来的话,注解配置开始讲了,这里面没什么道理,就是看怎么做就行了,第一步,需要为咱们的主配置文件,引入新的命名空间,或者叫做约束,昨天咱们导入的一个约束叫做beans,还记得吗,那个xsd文件,你要是玩注解配置,包倒不要倒什么新包,但是你的这个配置文件呢,是需要再导入一个新的约束的,那这里导入一个新的约束的话,我们自己都做过了,首先你得preferences cata

然后在这里add

spring,schema,咱们今天用的这个命名空间,第一个要用的命名空间,是咱们的context

导法和昨天一模一样,你把最后的名字复制,这里补个斜杠加上,然后在这里选择Schema Location

然后引入到eclipse就完事了

再到咱们的Application这里面,右键xml edit,切换到design视图

然后在beans上右键edit

Edit namespace,然后点击add

因为他就一条道,然后再点Browse

选下面这个

找到刚才导入的context命名空间,往下找,这儿呢,是这个

是这个吧,然后呢,剩下的事情,把前面这一段粘到这里来,http://www.springframework.org/schema/context,然后这里面听好,昨天的beans,Prefix前缀是空,但是在xml里面学过约束的知道,一个XML文档当中,只允许有一个空的前缀,昨天学那个beans为空,那以后导入的命名空间绝对不能够为空了,所以以后导入新命名空间,需要干这么一件事,把你刚才中间这一行,这一段的最后一个单词,复制粘贴到这里来,这就是前缀,相比昨天导beans,区别就在于,前缀昨天是空,然后从昨天以后,今天开始,再导新的,都要把后面这个复制过来

新的命名空间就导入进来了,然后保存退出,这个时候看一下,第二步使用注解代替配置文件,相当于打开一个使用注解的开关,这个开关的话,因为咱们要用啊,这个时候你打<context:前缀,就有很多context约束下的元素,然后我们用到的是component-scan,这个component单词知道是啥意思不,组件,scan就是扫描,翻译过来就是自动扫描,咱们指定的组件,在Spring里面组件就是对象,理解为对象,咱们把对象放在Spring容器里管理,在Spring官方来说,把Component都放进来了,把组件放进来,所以理解成对象的扫描,后面这个是啥意思,base-package,基础包,他的意思就是给他一个包名,从包下去扫描所有的类,扫这个包下的所有的类,看上面有没有注解,咱们放到容器这两个对象,都是在这个bean包下边,所以你把bean包这个包名放到这,这是指定扫描这个包下的所有类中的注解,这里需要注意的是,在扫描包的时候,他不仅仅只扫描你给的这个包,如果这个包还有子包的话,也会扫描的,知道啥意思不,假设这个bean包下还有个haha包,这也会扫描,haha下边还有个heihei包,也就是他在扫描的时候,他需要扫描子孙,所有包的,当然你这个learn这个包扫不扫,这个不扫,只扫你这个包的子包和子孙包,他之前的父包和爷包都不扫,这里面注意,在扫描时,扫描包时,会扫描指定包下的所有子孙包,当然很多人为了省事,比如全项目当中,所有项目都想用注解,他们就可能配置成这样了,知道啥意思吗,这样就覆盖了所有,我们还是讲bean,这样的话第一步就完事了,把这个截个图放到这儿,这样的话加个配置就可以了,然后接下来第三步,第三步就是在类中使用注解,完成配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd "><!-- 指定扫描com.learn.bean这个包下的所有类的注解 注意:扫描包时,会扫描指定包下的所有子孙包--><context:component-scan base-package="com.learn.bean"></context:component-scan></beans>
比如我们想把User对象配置到咱们的Spring容器当中,怎么做,这个构造我都给他删掉,想把User对象配置到Spring容器当中的话,加上一个注解,@Component,这个叫组件,人家规定这个组件意思可明确了,那就是把User注册到Spring容器中,这就是组件了,你也可以通过括号指定一个参数,这个参数的话用来指定对象放到Spring当中的这个名称是什么,比如叫user,这个写完以后,相当于在我们XML里面,怎么配置,<bean name="user">,然后class就是我们的User,你加这么一个注解,就相当于在这里面配置这个,咱们可以试一下,就加这一个注解,是不是好使,然后复制一个Demo过来,测试类过来
package com.learn.bean;import org.springframework.stereotype.Component;@Component("user")
// <bean name="user" class="com.learn.bean.User">
public class User {public User() {System.out.println("User空参构造方法");}private String name;private Integer age;private Car car;public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public void init() {System.out.println("我是初始化方法!");}public void destory() {System.out.println("我是销毁方法!");}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
a_annotation注解,在这创建容器,我把这个注释打开就可以了,接下来你看,能不能获得咱们注册进来的User,不能,报错了,报啥错呢
package com.learn.a_annotation;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.learn.bean.User;public class Demo {/*** 创建方式1:空参构造*/@Testpublic void fun1() {/*** 1.创建容器*/ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");/*** 2.向容器要"user"对象*/User u = (User)ac.getBean("user");/*** 打印user对象*/
//      System.out.println(u);}
}
咱们这个要玩注解的话,还得导一个包,他需要导入AOP包,老版本的不需要,spring-aop-4.2.4.RELEASE.jar,我们把这个步骤添加上,这个是新版本的

这个模块在这里还要用到的,导完这个包之后,接下来再执行一下,是不是就获取到这个对象了,这个时候就使用到了Component注解了,代替了咱们的bean语言,当然这里还有一个问题就是,Component这个注解,Spring在注册bean的时候,一个早期注解,后来呢,又出现了这么几个注解,@Service注解,user,还有@Controller,还有@Repository注解,后来又衍生出来这三个注解,啥意思呢,当年刚出现注解的时候,注册bean只有一个注解,就是Component,后来使用者给Spring反馈,咱们注册项目当中所有对象的时候,都用的同一个注解,这样的话通过注解,很难区分对象是属于哪一层,Spring听了以后说,想一想,那咱们这样解决吧,我再找出来三个注解,这三个注解和Component没有任何区别,但是呢,这三注解,通过他的名字,你就能知道,你注册的对象是属于哪一层的对象,换句话讲,对我们使用者来说,要想注册一个Service层的对象,那你是不是可以使用这个注解,用于注册Service层,那这个Controller,注册什么层的呢,WEB层,为啥是WEB层,这个我们讲MVC的时候,WEB就是servlet,或者咱们的action之类的,Repository其实是仓库的意思,仓库指的就是数据仓库,数据库,所以它是用来注册DAO层的,所以我们要学如何把对象注册到容器当中,一共有四种办法,但是推荐使用能够体现分成的三种,这个是具体注解,将对象注册到容器中,就使用这三个注解,就这么简单,然后接下来
package com.learn.bean;import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
//  @Service("user")
//  @Controller("user")@Repository("user")
public class User {private String name;private Integer age;private Car car;public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}}
这四个用哪个都一样,接下来第二个,咱们学会怎么注册bean之后,比如这个User对象,怎么决定他的作用范围,是单例的,还是prototype多例的,这个是可以使用@Scope属性,你可以指定他的scopeName,如果是单例的话就是singleton,如果是原型就是prototype,单例因为是默认值,你改单例就不用加了,你要用的话肯定是改原型,那咱们来测一下
package com.learn.bean;import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
//  @Service("user")
//  @Controller("user")@Repository("user")@Scope(scopeName="prototype")
public class User {private String name;private Integer age;private Car car;public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}}
这个可以复制一份,u1,u2,是单例还是原型,打印一下u1==u2,那接下来咱们试一下,咱们改成原型,势必导致是false
package com.learn.a_annotation;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.learn.bean.User;public class Demo {/*** 创建方式1:空参构造*/@Testpublic void fun1() {/*** 1.创建容器*/ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");/*** 2.向容器要"user"对象*/User u1 = (User)ac.getBean("user");User u2 = (User)ac.getBean("user");System.out.println(u1==u2);/*** 打印user对象*/
//      System.out.println(u);}
}
比如我这个去掉,看他默认是不是单例的,执行一下,是不是true啊
package com.learn.bean;import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
//  @Service("user")
//  @Controller("user")@Repository("user")
//  @Scope(scopeName="prototype")
public class User {private String name;private Integer age;private Car car;public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}}
package com.learn.a_annotation;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.learn.bean.User;public class Demo {/*** 创建方式1:空参构造*/@Testpublic void fun1() {/*** 1.创建容器*/ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");/*** 2.向容器要"user"对象*/User u1 = (User)ac.getBean("user");User u2 = (User)ac.getBean("user");System.out.println(u1==u2);/*** 打印user对象*/
//      System.out.println(u);}
}
package com.learn.bean;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
//  @Service("user")
//  @Controller("user")@Repository("user")
//  @Scope(scopeName="prototype")
public class User {@Value("tom")private String name;private Integer age;private Car car;public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
package com.learn.a_annotation;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.learn.bean.User;public class Demo {/*** 创建方式1:空参构造*/@Testpublic void fun1() {/*** 1.创建容器*/ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");/*** 2.向容器要"user"对象*/User u1 = (User)ac.getBean("user");/*** 打印user对象*/System.out.println(u1);}
}
所以这里使用scope,指定对象的作用范围,这是咱们学习的第二个知识点,修改对象的作用范围,那下面咱们还要学习关于属性的注入,比如说这个用户,来给他一个名字,怎么做呢,很简单,使用注解的话,是使用@Value的注解,Value就是值,括号,这里你要填写一下,你要注入的值是什么,比如用户咱们给他一个名字,tom,这是不是给name属性赋值,赋值是tom,相当于什么玩意,相当于这里加一个property,这我就不去写了,你们知道这是啥意思吧,就是把tom这个值注入到name属性中,然后呢,直接执行一下,看控制台打印,
User [name=tom, age=null, car=null]是不是有效果
但是跟你拓展一下,咱们这个使用value属性,注入值的时候,有两种选择实际上,一种是把value属性直接加载成员变量内部上,还有一种是把注解加载setName方法上,加在这里也是可以的
package com.learn.bean;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
//  @Service("user")
//  @Controller("user")@Repository("user")
//  @Scope(scopeName="prototype")
public class User {private String name;private Integer age;private Car car;public String getName() {return name;}@Value("tom")public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
package com.learn.a_annotation;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.learn.bean.User;public class Demo {/*** 创建方式1:空参构造*/@Testpublic void fun1() {/*** 1.创建容器*/ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");/*** 2.向容器要"user"对象*/User u1 = (User)ac.getBean("user");/*** 打印user对象*/System.out.println(u1);}
}
User [name=tom, age=null, car=null]
考虑一下,这两种有什么区别,一种是加在成员变量上的,还有一种是加在set方法上,这其实挺矛盾的,说起来,为什么矛盾呢,你加在成员变量上,Spring在给这个对象赋值的时候,它是直接对field字段进行赋值,对field字符按进行赋值,学过反射吗,知道Field是啥东西吗,它是操作字段进行赋值的,而如果你放在setName上,他走的是set方法赋值的,通过反射的Field进行赋值,而下面是通过set方法赋值,这就是区别,当然对于我们赋值的结果来说,好像都一样,但是从技术上来讲,上面这种方式来赋值的话,破坏了咱们对象的封装性,知道啥是破坏封装性吗,这是学面向对象最基础的理论,面向对象三个特点,封装,继承和多态,啥叫封装,怎么举例子的,就是装电脑,然后你把CPU,硬盘装好之后,是不是要放到机箱里,放到机箱里的过程就叫做封装,封装的目的是啥啊,就是没有必要直接去访问到里面的CPU,那么你一摸就摸坏了,所以,把电脑的硬件都放在机箱里,什么音频插口,USB插口,是不是这个意思,那咱们封装类是不是也如此,封装类的时候,把不希望外界看到的属性私有,然后只暴露共有的对外的操作的方法,get和set,是这个意思吗,那要是加在成员变量上,那是不是就直接访问到内部的成员变量了,这是一个私有的,明白啥意思吗,所以他是破坏了封装性,破坏了封装性就是面向对象,然后通过set方法赋值,它是推荐的,推荐使用,那毛病就毛病在这,在成员变量上加多清爽痛快,在方法上加是多别扭,所以咱们日常使用的时候,反正效果是一样的,可能没有人在意这个东西了,大家都喜欢加载属性,成员变量上,这个仁者见仁智者见智,感觉是一个取舍问题呢,然后呢这就是value属性,这块的话给age也赋上一个值,括号给他来一个18岁,value等于18,注解学过吧,如果属性只有一个,并且名字是value,就可以忽略属性的键,记住这就是一个结论,如果注解中只有一个需要赋值,并且属性名是value的话,那你是可以忽略属性键的,所以凡是不写键的,都是给什么属性赋值,都是给value属性赋值
package com.learn.bean;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
//  @Service("user")
//  @Controller("user")@Repository("user")
//  @Scope(scopeName="prototype")
public class User {private String name;@Value(value="18")private Integer age;private Car car;public String getName() {return name;}@Value("tom")public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
User [name=tom, age=18, car=null]
然后age赋完值以后执行一下,是不是没问题
然后呢再往下,又该赋值了,只是赋值跟以前不太一样了,以前是值,现在是对象,那这个的话看好,给对象赋值呢,这块的话有点讲究,你要是想把car属性赋值过来,首先你要把Car注册到容器当中,所以在Car上加上@Component,然后括号,在这里给他取一个名字,car,这样的话car就放到容器当中了,接下来我要把car注入给user
package com.learn.bean;import org.springframework.stereotype.Component;@Component("car")
public class Car {private String name;private String color;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}@Overridepublic String toString() {return "Car [name=" + name + ", color=" + color + "]";}}
看我这怎么写,有这么几种方式,第一种方式,也就是最简单的方式,只要加一个注解,@Autowired,这就完事了,只要加一个Autowired,Car就会被封装进来,你看一下Car对象是不是有值了
package com.learn.bean;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
//  @Service("user")
//  @Controller("user")@Repository("user")
//  @Scope(scopeName="prototype")
public class User {private String name;@Value(value="18")private Integer age;@Autowiredprivate Car car;public String getName() {return name;}@Value("tom")public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
User [name=tom, age=18, car=Car [name=null, color=null]]
Car name昨天是兰博基尼,今天来个什么,玛莎拉蒂,然后color,来个呕吐绿,再执行下你看看,是不是就进去了
package com.learn.bean;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component("car")
public class Car {@Value("玛莎拉蒂")private String name;@Value("呕吐绿")private String color;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}@Overridepublic String toString() {return "Car [name=" + name + ", color=" + color + "]";}}
是不是就给了一个user,这就是第一种方式,叫Autowired,这个单词,Auto是不是自动,wire是不是穿衣服的穿,翻译一般翻译成自动装配,那有的人说好神奇,怎么自动装配的,符合这个类型的对象,如果检测到的话,找到这个对象,那你想,现在一看,这个Car类型,加了Autowired的,是不是会去容器中找Car类型的对象,那是不是能找着,找着了一个Car,是不是就给他了,知道啥意思不,那这种写法,爽是爽,但是对象一多的时候会有这个问题,你们猜到了,啥问题,这种自动装配的方式,假设我要把这个Car,注册了好几辆在容器当中呢,听懂啥意思不,比如我有三辆车,在容器当中,那怎么能做到呢,你在这里放一个传统的bean,来一个name,再来一个什么,class,这也是咱们的Car,然后这一块叫做car2,咱们这一块再来一个属性,比如property,name等于name,value是布加迪威龙,那这样的话再看,现在我Spring容器当中,是不是两辆车
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd "><!-- 指定扫描com.learn.bean这个包下的所有类的注解 注意:扫描包时,会扫描指定包下的所有子孙包--><context:component-scan base-package="com.learn.bean"></context:component-scan><bean name="car2" class="com.learn.bean.Car"><property name="name" value="布加迪威龙"></property><property name="color" value="black"></property></bean></beans>
package com.learn.a_annotation;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.learn.bean.User;public class Demo {/*** 创建方式1:空参构造*/@Testpublic void fun1() {/*** 1.创建容器*/ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");/*** 2.向容器要"user"对象*/User u1 = (User)ac.getBean("user");/*** 打印user对象*/System.out.println(u1);}
}
那我这个自动装配的话,它是按照类型会去容器中匹配,那这样的话,你给他这么一装他就迷茫了,哪辆呢,你看玛莎拉蒂User [name=tom, age=18, car=Car [name=玛莎拉蒂, color=呕吐绿]]
第一种方式有个问题,就是如果有多个类型的话,他自动装配的话,自动装配的话又有一个问题,如果匹配到多给类型一致的对象,将无法选择具体注入哪一个对象,这样的话怎么办呢,咱们给Autowired加一个辅助注解,@Qualifer,然后这个注解,填入一个你要注入的名字,就像布加迪威龙,刚才咱们注册的叫car2,那你就在这写上,car2,知道啥意思,这样的话等于说自动装配,告诉他找名为car2的车
package com.learn.bean;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
//  @Service("user")
//  @Controller("user")@Repository("user")
//  @Scope(scopeName="prototype")
public class User {private String name;@Value(value="18")private Integer age;/*** 自动装配* 问题:如果匹配多个类型一致的对象,讲无法选择具体注入哪一个对象*/@Autowired@Qualifier("car2")private Car car;public String getName() {return name;}@Value("tom")public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
User [name=tom, age=18, car=Car [name=布加迪威龙, color=black]]
看到效果了吗,这样的话怎么找都是布加迪威龙,这样的话他就是第二种方式,使用Qualifier,使用@Qualifier注解,告诉咱们的Spring容器,自动装配哪个名称的对象,这里成对配套使用,然后最后再介绍一种方式,这两个先注掉,其实如果你是对象类型,有多个的话,其实并不建议你用这两个注解一块用,这样用太罗嗦了,有一个注解他不是自动装配,直接指名道姓的,叫做Resource属性,指名道姓的告诉他要装配哪一个,car2,这样的话一个注解,是不是就搞定了,他不是自动注解,他完全是手动注解,手动注入,指定注入哪个名称的对象,这样的话是不是还是注入布加迪威龙,执行一下你看看,是不是这个效果
package com.learn.bean;import javax.annotation.Resource;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
//  @Service("user")
//  @Controller("user")@Repository("user")
//  @Scope(scopeName="prototype")
public class User {private String name;@Value(value="18")private Integer age;/*** 自动装配* 问题:如果匹配多个类型一致的对象,讲无法选择具体注入哪一个对象*/
//  @Autowired
//  @Qualifier("car2")/*** 手动注入,指定注入哪个名称的对象*/@Resource(name="car2")private Car car;public String getName() {return name;}@Value("tom")public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
User [name=tom, age=18, car=Car [name=布加迪威龙, color=black]]
你要想输出玛莎拉蒂,再执行一下
package com.learn.bean;import javax.annotation.Resource;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
//  @Service("user")
//  @Controller("user")@Repository("user")
//  @Scope(scopeName="prototype")
public class User {private String name;@Value(value="18")private Integer age;/*** 自动装配* 问题:如果匹配多个类型一致的对象,讲无法选择具体注入哪一个对象*/
//  @Autowired
//  @Qualifier("car2")/*** 手动注入,指定注入哪个名称的对象*/@Resource(name="car")private Car car;public String getName() {return name;}@Value("tom")public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
User [name=tom, age=18, car=Car [name=玛莎拉蒂, color=呕吐绿]]
是不是这个效果,这就是第三种注入对象的方式了,然后呢其中,推荐的话我其实推荐这种,这就是三种对象类型的注入方式,然后咱们以后最好的方式,就是指名道姓,直接指定注入哪一个,这是类型注入,接下来还没有完,最后有两个注解,比如说这个User,咱们指定一个初始化方法,销毁方法,咱们配置文件不是学了,pubilc void init方法,这个就打印一下,这是初始化方法,比如这个init方法我想让他作为初始化方法,可以在他这个方法上加上一个@PostConstruct,这个单词翻译过来,post是在什么之后,Construct是不是构造,所以翻译过来是什么,构造之后调用,在对象被构造后,或者是被创建吧,创建后调用,相当于咱们以前学过的什么东西,init-method,然后这个destory方法,叫做@PreDestroy,PreDestroy,Pre是在什么之前,Destory是销毁,在对象销毁之前,调用的,相当于destroy-method,知道啥意思不
package com.learn.bean;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
//  @Service("user")
//  @Controller("user")@Repository("user")
//  @Scope(scopeName="prototype")
public class User {private String name;@Value(value="18")private Integer age;/*** 自动装配* 问题:如果匹配多个类型一致的对象,讲无法选择具体注入哪一个对象*/
//  @Autowired
//  @Qualifier("car2")/*** 手动注入,指定注入哪个名称的对象*/@Resource(name="car")private Car car;/*** 在对象被创建后调用.init-method*/@PostConstructpublic void init() {System.out.println("初始化方法!");}/*** 在销毁之前调用 destroy-method*/@PreDestroypublic void destory() {System.out.println("销毁方法!");}public String getName() {return name;}@Value("tom")public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
那接下来咱们再试一下看看,这里面咱们的销毁方法,你要想看到打印的话,你要调用它的close方法,那这个close方法要调的话,引用得用子类,然后最后来一个ac.close,这回你再执行你看看,看到这个效果了
package com.learn.a_annotation;import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.learn.bean.User;public class Demo {/*** 创建方式1:空参构造*/@Testpublic void fun1() {/*** 1.创建容器*/ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");/*** 2.向容器要"user"对象*/User u1 = (User)ac.getBean("user");/*** 打印user对象*/System.out.println(u1);ac.close();}
}
初始化方法!
User [name=tom, age=18, car=Car [name=玛莎拉蒂, color=呕吐绿]]
销毁方法!
作用域改成singleton,为啥呢,每次都创建一个新的,每次新的给你就不管了,只有放在容器中的才会纳入完整性里面,看到了效果了,这样的话这就是咱们的初始化和销毁,初始化销毁,初始化以及销毁方法,这样的话咱们注解就到这,这是Spring当中的注解,代替配置文件

spring中使用注解代替xml配置相关推荐

  1. spring中的注解和xml配置文件中配置对应总结

    spring中的注解和xml配置文件中配置对应 需要导入的jar spring-context spring-context-support spring-test commons-logging b ...

  2. MongoDB和Java(4):Spring Data整合MongoDB(XML配置)

    最近花了一些时间学习了下MongoDB数据库,感觉还是比较全面系统的,涉及了软件安装.客户端操作.安全认证.副本集和分布式集群搭建,以及使用Spring Data连接MongoDB进行数据操作,收获很 ...

  3. spring 加载java类_在Spring中基于Java类进行配置的完整步骤

    在Spring中基于Java类进行配置的完整步骤 发布于 2020-7-7| 复制链接 基于Java配置选项,可以编写大多数的Spring不用配置XML,下面 前言JavaConfig 原来是 Spr ...

  4. Spring中常用注解的介绍

    spring中使用注解时配置文件的写法: <?xml version="1.0" encoding="UTF-8"?> <span style ...

  5. 声明式事务、Spring 中常用注解、Ajax

    五. 声明式事务 编程式事务: 1.1 由程序员编程事务控制代码. 1.2 OpenSessionInView 编程式事务 声明式事务: 先引入依赖 <dependency><gro ...

  6. java快速注释怎么配置_详解如何在低版本的Spring中快速实现类似自动配置的功能...

    在 Spring 4 后才引入了 @Conditional 等条件注解,它是 Spring Boot 中实现自动配置的最大功臣! 那么问题来了:如果我们还在使用 Spring 3.x 的老版本,这时候 ...

  7. spring中自定义注解(annotation)与AOP中获取注解___使用aspectj的@Around注解实现用户操作和操作结果日志

    spring中自定义注解(annotation)与AOP中获取注解 一.自定义注解(annotation) 自定义注解的作用:在反射中获取注解,以取得注解修饰的类.方法或属性的相关解释. packag ...

  8. Spring 中所有注解

    Spring中的注解主要分为两类: 类级别的注解: 如@Component.@Repository.@Controller.@Service以及JavaEE6的@ManagedBean和@Named注 ...

  9. java 外部覆盖内部配置,Spring 与自定义注解、外部配置化的结合使用

    Spring 与自定义注解.外部配置化的结合使用 一.Java注解的简单介绍 注解,也叫Annotation.标注,是 Java 5 带来的新特性. 可使用范围 类.字段.方法.参数.构造函数.包等, ...

最新文章

  1. Linux多线程同步------条件变量
  2. Oracle Database 11.2.0.1(静默安装)
  3. 嵌入式Linux下S3C2410的调色板彩色显示
  4. python如何创建模块教程_Python创建模块及模块导入的方法
  5. quartz Cron-Expression的表达式
  6. 【翻译】eXpressAppFramework QuickStart 业务模型设计(十)——在代码中实现数据验证...
  7. 大容量导入和导出数据 -- 格式化文件生成
  8. python字典长度可变吗_Python字典dict实现原理
  9. (13)ZYNQ AXI总线应用范围(学无止境)
  10. docker集群——介绍Mesos+Zookeeper+Marathon的Docker管理平台
  11. python怎么看自己安装的第三方包_安装第三方包查看python版本/第三方包版本
  12. java 根据银行卡号来获取银行名称
  13. photoshop图片放大不失真
  14. android自动调节背光,android自动调节背光
  15. uWSGI, Gunincorn, 啥玩意儿?
  16. java生成vcf_Android vcard使用示例,生成vcf文件
  17. ipv4和ipv6地址长度
  18. 2019年日历 打印 备注_2010年日历:可打印的日历和墙纸
  19. 基于SpingBoot2.0与activiti7.x构建的一套工作流程管理系统
  20. mysql plus多表关联_结合mybatis-plus 实现实体操作多表关联查询

热门文章

  1. rfid2-micro2440,keil4裸机
  2. Open 5分钟:恺英收集闵懿
  3. Javascript的变量作用域居然可以跨越多个函数!
  4. Linux服务器下搭建JDK、Tomcat环境和部署web应用
  5. gitlab增加日志
  6. 在Centos上编译安装nginx
  7. linux 免密码登录
  8. flask中的信号机制
  9. 08-Windows Server 2012 R2 会话远程桌面-标准部署-使用PowerShell进行部署2-1
  10. 邮件列表统计(网站推广)