-
控制反转的解释
查看全部 -
AOP相关概念
查看全部 -
aop实现方式
预编译AspectjJ
SpringAOP
JbossAOP
查看全部 -
aop概念和主要功能
查看全部 -
框架和类库
查看全部 -
一、接口及面向接口编程
接口:
1、用于沟通的中介物的抽象化。(相当于中间者,外部与接口沟通,但不与接口实现类进行沟通)
2、实体把自己提供给外界的一种抽象化说明,用以由内部操作分离出外部沟通方法,使其能被修改内部而不影响外界其他实体与其交互的方式(接口提供外部功能,至于内部的具体实现不对外公开,比如:注册,只需要提供手机号、密码等信息就可以进行注册,具体怎么实现的,逻辑怎样判断的,数据存储在哪里等具体实现逻辑不对外公开)
3、对应java接口即声明,声明了哪些方法是对外公开提供的,在Java8中,接口可以拥有方法体,(某种程度上和抽象类具有相似的功能)。
面向接口编程:
1、结构设计中,分清层次及调用关系,每层只向外(上层)提供一组功能接口,各层间仅依赖接口而非实现类。(多态的体现)
2、优点:接口实现的变动不影响各层间的调用,这一点在向外提供公共服务或者在企业内部提供公共服务中尤为重要,由于公共服务,所以稳定性一定很重要(对外提供接口保证了接口的稳定性,对于接口的实现可以根据某一时期的具体情况或者某一时期具体逻辑的变化进行调整)
3、面向接口编程中的“接口”:用于隐藏具体实现和实现多态性的组件,面向接口编程在IOC中应用非常广泛(对外提供调用说明的,但不包含具体的实现,具体的实现由接口实现类完成)
二、什么是IOC
IOC概念:(Inversion of Control)控制反转,控制权的转移,应用程序本身不负责依赖对象的创建和维护,而是由外部容器负责创建(创建对象并且组装对象之间的依赖关系)和维护(正常情况下使用对象则需要new对象,而使用外部容器之后,对象就被容器管理了,包括对象的创建、初始化、销毁等,对象就可以直接从容器中直接拿过来用),IOC容器在初始化时,会创建一系列的对象,同时把对象之间的依赖关系通过注入的方式组织起来。(组装:一个类A,和一个类B,类A把类B作为自己的属性,当IOC进行实例化时,先实例化A,再实例化B,再把B注入到A中)
比喻:我们手动去new一个对象,就像我们想要一所房子,我们自己手动的买材料去建造,而使用容器之后,就像找开发商,直接可以入住房子。
DI概念:(Dependency Injection)依赖注入,控制反转的一种实现方式,获得依赖对象的过程由自身管理变为了由IOC容器主动注入,所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。
IOC目的:创建对象并且组装对象之间的关系(IOC容器在初始化时,会初始化一系列的对象,同时能把对象之间的依赖关系通过注入的方式组织起来)例如:一个类A里存在另一个类B的声明,IOC会负责创建A和B的对象,并通过A的构造方法注入B的实例。
Spring官网给出IOC工作原理
描述IOC
三、Spring的Bean配置
1、在IOC容器中所有的对象都称为Bean。
2、Spring的Bean配置方式有两种:基于XML配置、注解配置。
3、XML中配置:<bean id="bean的唯一标识",class="交给容器管理的类的路径"></bean>
四、Bean容器的初始化
基础:两个包:
org.springframework.beans
org.springframework.context
beans提供BeanFactory及其子类,它提供配置结构和基本功能,并加载初始化Bean
context提供ApplicationContext及实现类保存了Bean对象并在Spring中被广泛使用
初始化ApplicationContext方式:
1、加载本地文件(指定磁盘下某路径下的xml文件)
2、Classpath(相对路径,相对项目的路径)
3、Web应用中依赖servlet或Listener初始化Bean容器(两种方式,任选其一)
例子:
查看全部 -
Resources:针对资源文件的统一接口,通过Spring加载一些资源文件的时候,可以通过它去控制。
——UrlResource:URL对应的资源,根据一个URL地址即可构建Resources。
——ClassPathResoure:获取类路径下的资源文件(相对路径)。
——FileSystemResource:获取文件系统里面的资源(绝对路径)。
——ServletContextResource:ServletContext封装的资源,用于访问ServletContext环境下的资源。(和Web相关的资源文件的入口)
——InputStreamResource:针对于输入流封装的资源。(构建它需要InputStream)
——ByteArrayResource:针对于字节数组封装的资源。(构建它需要ByteArray)
ResourceLoader:对Resource加载的一个类,在SpringIOC容器中,所有的ApplicationContext都实现了ResourceLoader接口,所有的ApplicationContext都可以用来获取Resource实例,所以可以通过getResource(String location)方法获取资源Resource。
ResourceLoader接口的声明(有个方法,输入为文件的位置,返回的是Resource的实例)
ResourceLoader注入参数时前缀的几种类型
ResourceLoader前缀:classpath:(相对路径,加载文件)
file:(绝对路径,加载文件)
url: http(web路径、加载文件)
(none):直接输入路径,依赖ApplicationContext
案例:(Bean通过实现ApplicationContext接口,间接的实现了ResourceLoader接口(加载Resource实例),就可以使用getResource()获取Resource的实例,Resource拥有一系列的方法,比如获取文件名称(getFilename()和获取文件长度contentLength())
步骤1:
public class ResourceDemo implements ApplicationContextAware {
private ApplicationContext ac;
@Override
public void setApplicationContext(ApplicationContext ac) throws BeansException {
this.ac=ac;
}
public void resource() throws IOException{
Resource r=ac.getResource("classpath:resourceDemo.txt");(直接写文件,而不写全路径,是因为Java build path 配置了source,所以这里是相对路径)
System.out.println(r.getFilename());
System.out.println(r.contentLength());
}
}
步骤2:
<bean id="resourceDemo" class="ResourceDemo" ></bean>
步骤3:
@Test
public void testBean() throws IOException{
ApplicationContext ac=new ClassPathXmlApplicationContext("spring-ioc.xml");
ResourceDemo rd=(ResourceDemo)ac.getBean("resourceDemo");
rd.resource();
}
测试:
@Test
public void testBean() throws IOException{
ApplicationContext ac=new ClassPathXmlApplicationContext("spring-ioc.xml");
ResourceDemo rd=(ResourceDemo)ac.getBean("resourceDemo");
rd.resource();
}
结果:(文件:resourceDemo.txt,在src——>resource文件夹下)
resourceDemo.txt
6
案例:file方式
案例:url方式
查看全部 -
Bean管理的注解实现及例子
1、Classpath扫描与组件管理
定义:从Spring3.0开始,Spring JavaConfig项目提供很多特性,包括通过注解定义Bean,而不是使用XML。
@Component:通用型注解,可用于任何Bean。
@Repository:通常用于注解DAO类,即持久类。
@Service:通常用于注解Service类,即服务层。
@Controller:通常用于注解Controller,即控制层。
2、类的自动检测与注册Bean
定义:Spring可以检测到类上和属性上以及方法上的注解,可以通过注解进行实例化或注入。
3、<context:annotation-config/>
定义:基于XML配置,如果使用该标签,则在描述中添加约束。
<context:component-scan>:一般处理类上的注解,它的功能包含<context:annotation-config>的功能,比较常用。
<context:annotation-config>:一般处理实例化Bean的属性和方法的注解。
SpringXML配置过滤器作用:扫描特定包下的特定注解。
4、@Component,@Repository,@Service,@Controller
5、@Required
6、@Autowired
7、@Qualifier
8、@Resource
查看全部 -
一、可以使用@Autowired注解注入Spring提供的解析依赖性接口(ClassPathXmlApplicationContext、AnnotationApplicationContext、BeanFactory、Envieonment、ResourceLoader、ApplicatonEventPublisher、MessageSource)
二、可以对数组(集合)类型的属性进行注入,注入的是ApplicationContext中所有符合该类型或者是该类型的子类的(List<String>,则会把所有String类型的Bean注入List集合中)。
Key:Bean的Id。
Value:Bean的对象。
如果希望数组有序
1、Bean实现org.springframework.core.Ordered接口
2、@Order注解(只针对List)
InterfaceImplTwo添加@Order(value=1)
InterfaceImplOne添加@Order(value=2),先取出Two的实例,再取出One的实例。
@Autowired是由Spring BeanPostProcessor处理的,所以不能在配置类中使用它,也就是说要注入集合类型的属性,这些属性的值只能是通过xml或者在配置类中使用@Bean注解加载。
注入List<BeanInterface>代码:
public interface InjectInterface {
}
@Component
public class InterfaceImplOne implements InjectInterface {
}
@Component
public class InterfaceImplTwo implements InjectInterface {
}
@Configuration
@ComponentScan("injectList")
public class InterfaceConfig {
}
@Component(value="invoker")
public class InterfaceInvoker {
private List<InjectInterface> list;
@Autowired
public void setList(List<InjectInterface> list) {
this.list = list;
}
public void say(){
if(null!=list){
for (int i=0;i<list.size();i++) {
System.out.println(list.get(i));
}
}else{
System.out.println("list为null");
}
}
}
@Test
public void test(){
ApplicationContext ac=new AnnotationConfigApplicationContext(InterfaceConfig.class);
InterfaceInvoker ii=ac.getBean("invoker",InterfaceInvoker.class);
ii.say();
}
结果:
injectList.InterfaceImplOne@39f46204
injectList.InterfaceImplTwo@5b4f1255
注入Map类型<String,InjectInterface>类型属性(和List相似)
代码:
@Component(value="invoker")
public class InterfaceInvoker {
private Map<String,InjectInterface> map;
@Autowired
public void setMap(Map<String, InjectInterface> map) {
this.map = map;
}
public void say(){
if(map!=null&&map.size()>0){
for (Entry<String,InjectInterface> ii: map.entrySet()) {
System.out.println(ii.getKey()+" "+ii.getValue());
}
}
}
}
查看全部 -
@Qualifier:一般和@Autowired一起使用,按类型自动注入时可能会有多个Bean实例的情况,可以使用@Qualifier注解缩小范围(或指定唯一),也可用于指定单独的构造器或方法参数。
代码:
@Component(value="invoker")
public class InterfaceInvoker {
private List<InjectInterface> list;
@Autowired()
@Qualifier(value="one")
public void setList(List<InjectInterface> list) {
this.list = list;
}
public void say(){
if(null!=list){
for (int i=0;i<list.size();i++) {
System.out.println(list.get(i));
}
}else{
System.out.println("list为null");
}
}
}
@Component(value="one")
public class InterfaceImplOne implements InjectInterface {
}
@Component
public class InterfaceImplTwo implements InjectInterface {
}
结果:
injectList.InterfaceImplOne@54266750
xml文件中实现@Qualifier功能(不通过@Component)
查看全部 -
Java的容器注解说明——@Bean
@Bean:由SpringIoc容器配置和初始化对象,类似于XML配置文件的<bean/>,。(一般@Bean 需要在配置类中使用,即类上需要加上@Configuration注解)
@Bean的name属性:可以通过name属性指定Bean的Id,相当于XML中<bean>的Id。
@Component:如果一个类上标识该注解,表示配置类可以通过@ComponentScan("路径名")扫描到该类,并实例化这个类。
举例:
@Bean的initMethod属性、destroyMethod属性:通过@Bean实例化Bean时要执行的初始化和销毁逻辑。
查看全部 -
Java容器注解@ImportResource和@Value
一、通过xml文件进行配置。
<context:property-placeholder location="资源文件的存放位置"/>:<beans>进行配置,作用是加载资源文件(properties——Key-Value类型资源文件),然后就可以通过${Key},引用资源文件中的内容(如数据库的加载)。
代码:
public class Store {
public Store(String username,String password,String url){
System.out.println(username);
System.out.println(password);
System.out.println(url);
}
<context:property-placeholder location="classpath:/config.properties"/>
<bean id="store" class="Bean.Store">
<constructor-arg name="username" value="${jdbc.username}"></constructor-arg>
<constructor-arg name="password" value="${jdbc.password}"></constructor-arg>
<constructor-arg name="url" value="${jdbc.url}"></constructor-arg>
</bean>
测试:
@Test
public void test(){
ApplicationContext ac=new ClassPathXmlApplicationContext("spring-ioc.xml");
Store s=ac.getBean("store",Store.class);
System.out.println(s);
}
二、通过注解进行配置前提xml已经编写(配置类中添加@ImportResource("classpath:config.xml") )。
步骤1:配置类中添加@ImportResource,配置类中定好要用到的属性,并在属性上添加@Value("$(Key)")。
代码:
@Configuration
@ImportResource("classpath:/spring-ioc.xml")
public class StoreConfig {
@Value("${url}")
private String url;
@Value("${username}") //取到的是当前操作系统的用户名,所以不要使用username这个名。
private String username;
@Value("${password}")
private String password;
@Bean(name="store")
public Store getStoreBean(){
return new Store(username,password,url);
}
}
步骤二:这种注入依赖于使用@Bean标签,并返回有参构造函数对象,通过参数对Bean进行注入。
代码:xml代码:
<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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd" ,
<beans>中添加
<context:property-placeholder location="classpath:/config.properties"/>
java代码:
public class Store {
public Store(String username,String password,String url){
System.out.println(username);
System.out.println(password);
System.out.println(url);
}
配置文件:
username=\u5C0F\u660E
password=123456
url=localhost
查看全部 -
@Scope和@Bean
@Bean:默认是单例模式。
@Scope:value属性指定Bean的作用域范围,proxyMode属性指定使用的代理方式(包括接口的代理和类的代理)。
代理方式主要有两种:针对接口的代理、针对类的代理,实现方式有所区别。前者是jdk动态代理,后者是cglib代理。
proxyMode:容器启动时bean还没创建 通过cglib代理这个接口或者类注入到其它需要这个bean的bean中
查看全部 -
基于泛型的自动装配(Spring4新增的内容,和SPI使用方式相似,只不过Spring提供了更简便的使用方式。API:应用编程接口。SPI:针对服务框架开发或者一些工具的基础使用的特殊类型接口。)
基于依赖对象泛型的自动装配案例
步骤1:
public class IntegerStore {
}
public class StringStore{
@Autowired
private IntegerStore s2;
public void print(){
System.out.println("s2: "+s2);
}
}
步骤2:
@Configuration
public class StoreConfig {
@Bean
public StringStore stringStore(){
return new StringStore();
}
@Bean
public IntegerStore integerStore(){
return new IntegerStore();
}
}
步骤4:测试
@Test
public void testStore(){
ApplicationContext ac=new AnnotationConfigApplicationContext(StoreConfig.class);
StringStore ss=ac.getBean("stringStore",StringStore.class);
ss.print();
}
结果:(如果不加@Autowired注解,s2:为空)
s2: IntegerStore@3323f4c5
基于集合泛型的自动装配(注意:不能使用@Autowired注解,要使用@Resource注解,并且使用@Resource(name="名字1"),去匹配@Bean(name="名字1")。
步骤1:
public class IntegerStore {
}
public class StringStore {
public StringStore() {
System.out.println("无参构造方法执行了");
}
private List<IntegerStore> list;
@Resource(name = "ll")
public void setList(List<IntegerStore> list) {
this.list = list;
}
public void print() {
for (IntegerStore store : list) {
System.out.println(store);
}
}
}
步骤2:
@Configuration
public class StoreConfig {
@Bean(name = "ll")
public List<IntegerStore> ll() {
List<IntegerStore> lis = new ArrayList<IntegerStore>();
lis.add(new IntegerStore());
lis.add(new IntegerStore());
lis.add(new IntegerStore());
return lis;
}
@Bean(name = "stringStore")
public StringStore stringStore() {
return new StringStore();
}
}
测试:
@Test
public void testStore() {
ApplicationContext ac = new AnnotationConfigApplicationContext(StoreConfig.class);
StringStore ss = ac.getBean("stringStore", StringStore.class);
ss.print();
}
}
结果:
无参构造方法执行了
IntegerStore@2b2c8b14
IntegerStore@795ee430
IntegerStore@44d74990
Autowired扩展——自定义qualifier注解(自定义自动化注入配置)
查看全部 -
Spring Bean装配之Spring对JSR支持的说明
1:Spring支持使用JSR-250@Resource注解,通常用于成员变量和set方法上,这是一种在JavaEE5和6的通用模式(当然7也是支持的),Spring对对象的管理也支持这种方式。
2:@Resource有一个name属性,并且Spring默认把该name作为被注入bean的名称(如果没有显示指定name属性,默认名称是属性名或者set方法名,默认是根据注解的位置)。
3:注解提供的名字被解析为一个Bean的名称(@Resource的name属性),这个过程是由ApplicationContext中的CommonAnnotationBeanPostProcessor发现并处理的。
@PostConstruct和@PreDestroy
1:CommonAnnotationBeanPostProcessor不仅能识别JSR-250中的生命周期注解@Resource,在Spring2.5中引入支持初始化回调和销毁回调,前提是CommonAnnotationBeanPostProcessor这个类已经在Spring的ApplicationContext中注册了。(只有CommonAnnotationBeanPostProcessor类在IOC容器中注册了,才能处理@Resource,@PostConstruct,@PreDestroy)。
注意:自动注入,用Map<String,Object>map盛放所有的容器中的bean,然后循环打印所有的bean所属的类就能看到这个类了org.springframework.context.annotation.CommonAnnotationBeanPostProcessor,有这个类的bean。
@PostConstruct和@PreDestroy:这两个注解一般在的方法上,在初始化Bean和销毁之前,都会去调用这两个注解下的方法。
案例:(@Resource案例)
步骤1:
@Component
public class JsrDao {
public void print(){
System.out.println("JsrDao的方法执行了");
}
}
@Component
public class JsrService {
// @Resource
private JsrDao jsrDao;
public void print(){
jsrDao.print();
}
@Resource
public void setJsrDao(JsrDao jsrDao) {
this.jsrDao = jsrDao;
}
}
步骤2:
@Configuration
@ComponentScan
public class JsrConfig {
}
测试:
public class TestJsr {
@Test
public void testJsr(){
ApplicationContext ac=new AnnotationConfigApplicationContext(JsrConfig.class);
JsrService js=ac.getBean("jsrService",JsrService.class);
js.print();
}
}
结果:JsrDao的方法执行了
知识拓展:
@Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要导入,但是Spring支持该注解的注入。
1、共同点
两者都可以写在字段和setter方法上。两者如果都写在字段上,那么就不需要再写setter方法。
2、不同点
(1)@Autowired
@Autowired为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired;只按照byType注入。
public class TestServiceImpl { // 下面两种@Autowired只要使用一种即可 @Autowired private UserDao userDao; // 用于字段上 @Autowired public void setUserDao(UserDao userDao) { // 用于属性的方法上 this.userDao = userDao; } }
@Autowired注解是按照类型(byType)装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它的required属性为false。如果我们想使用按照名称(byName)来装配,可以结合@Qualifier注解一起使用。如下:
public class TestServiceImpl { @Autowired @Qualifier("userDao") private UserDao userDao; }
(2)@Resource
@Resource默认按照ByName自动注入,由J2EE提供,需要导入包javax.annotation.Resource。@Resource有两个重要的属性:name和type,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不制定name也不制定type属性,这时将通过反射机制使用byName自动注入策略。
public class TestServiceImpl { // 下面两种@Resource只要使用一种即可 @Resource(name="userDao") private UserDao userDao; // 用于字段上 @Resource(name="userDao") public void setUserDao(UserDao userDao) { // 用于属性的setter方法上 this.userDao = userDao; } }
注:最好是将@Resource放在setter方法上,因为这样更符合面向对象的思想,通过set、get去操作属性,而不是直接去操作属性。
@Resource装配顺序:
①如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
②如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
③如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
④如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。
@Resource的作用相当于@Autowired,只不过@Autowired按照byType自动注入。
@PostConstruct和@PreDestroy(和以上案例相似,主要增加两个方法,并关闭Spring上下文)
@Component
public class JsrService {
@Resource
private JsrDao jsrDao;
public void print(){
jsrDao.print();
}
public void setJsrDao(JsrDao jsrDao) {
this.jsrDao = jsrDao;
}
@PostConstruct
public void jsrInit(){
System.out.println("Bean初始化方法执行了");
}
@PreDestroy
public void jsrDestroy(){
System.out.println("Bean销毁方法执行了");
}
}
测试:@Test
public void testJsr(){
AbstractApplicationContext ac=new AnnotationConfigApplicationContext(JsrConfig.class);
JsrService js=ac.getBean("jsrService",JsrService.class);
js.print();
ac.close();
}
结果:(和XML文件配置的init-method和destroy-method一样的功能)
Bean初始化方法执行了
JsrDao的方法执行了
Bean销毁方法执行了
使用JSR330标准注解
1:从Spring3.0开始支持JSR330标准注解(依赖注入注解),其扫描方式与Spring注解一致。
2:使用JSR330需要依赖javax.inject包。
3:使用Maven引入方式如下。
@Inject注解:等效于@Autowired,可以使用于类、属性、方法、构造器上。
@Named注解:使用特定名称进行依赖注入,与@Qualifier是等效的,还可以注解在类上,相当于@Component。(同一种类型的Bean在IOC容器中有多个时候,可以使用@Named指定特定的Bean)
在方法上:
在类上:
案例:@Inject和@Named
把@Componet换成@Named,@Resource换成Inject,执行结果相同。
查看全部
举报