博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2019.6.18 spring的xml和注解
阅读量:4160 次
发布时间:2019-05-26

本文共 10287 字,大约阅读时间需要 34 分钟。

spring概要

bean对象的控制反转(IOC)和属性的依赖注入(DI)

spring中对于对象(bean)的三种配置:

(1)常见bean的无参构造的配置

(2)工厂类普通方法中创建的bean的配置

public class Bean3Factory {	public Bean3 getBean3(){		return new Bean3();	}}
//注意创建上面bean3的实例的话,id标识要以下面bean3为准奥,上面那个id只是负责定位上面那个类,下面才是入口//通过下面id确定工厂类的id名为bean3Factory,即定位到cn.itcast.spring.demo3.Bean3Factory类,并且定位//到工厂中factory-method方法。最终就完成bean3对象的定位输出。

(3)工厂类静态方法中创建bean的xml的配置

public class Bean2Factory {	public static Bean2 getBean2(){		return new Bean2();	}}
//被spring管理的类是工厂类,但该类方法下创建实例,所以要声明出方法

spring中对于对象(bean)内属性注入的四种情况:

(1)属性通过构造方式的注入,这情况下属性的标识符是 constructor-arg

(2)属性通过set方式的注入,这情况下属性的标识符是 property

(3)引用类型的属性的注入

//id 是该bean唯一身份标识奥!
//person类中属性是引用类型,这时在标签property中设置引用参数和普通参数就不同了。//普通参数是name=属性名称 value=该属性赋的值。//引用参数是name = 属性名称 ref = 该引用类型对应的bean的id,告知spring去找到该类型的bean,才能帮创建对象奥!

(4)复杂类型的属性注入:集合等

会希
冠希
天一
芙蓉
如花
凤姐
root
123

控制反转(IOC)注解方式

注解的好处是免了在xml文件中手动注册bean,由spring框架自动向spring容器中注册bean。如@component及其下一些@service、@controllerspring容器中注入bean到变量中

上面是ioc的xml的配置,下面对于其注解的方式
(1)首先引入jar包,在原ioc六个包基础上多了个aop-jar包,因为注解就在里面。
(2)在类路径下创建applicationcontext.xml核心配置文件。(配置文件后,要引入约束,这样有提示)注解要引入context约束。
(3)下面准备类数据,这些都和xml配置文件一样,只是在核心配置文件中不用配置《bean id = “xx” class=“xxx”》了,首先配置注解扫描,用于告诉spring哪些包下哪些类是使用了注解,要你去扫描解析,而不是配置文件的解析(注解的方式其本质上相当于手动在配置文件中设置的作用是一样的。所以注解扫描就可以了,不用在配置文件中去查找bean或者property的配置了)。 就类似于开启了注解模式;如:

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//告知框架,在哪个包下的类都用注解解析。开启组件扫描模式。

(4)下面就在类上通过注解将类交给spring就ok了(@Component(value=“mycar”) //相当于<bean id=“mycar” class=“被注解的类型”)注解本质也是将标识的目标装配到spring的核心配置文件中。类似于手动配置bean或者property一样。

@Component(value="mycar") //相当于
public class mycar implements car { public void start() { System.out.println("我的车启动了1。。。"); } public void run() { System.out.println("我的车上路了1。。。"); } public void stop() { System.out.println("我的车熄火了1。。。"); }}

(5)上面就完成了控制反转,然后测试一下

public class car_test {@Testpublic void demo2() {	ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext.xml");	car car = (car)context.getBean("mycar");	car.stop();}}结果:我的车熄火了1。。。

IOC的注解形式和详解

主要是 控制反转类 的 注解 和 属性 的注解

上面发现注解方式免了配置文件中各种设置了,方便了实际开发。但如果改动,还要改源代码,这是弊端。

  • 上面是对象的注解,那属性注入如何注解
  • 基本属性注入的注解——就是在属性上通过@value(“属性值”)就ok了,可以没有set方法奥!有set方法注解就写在方法上,没有就直接写在属性上
@component(类的注解

作用:就是修饰类的,将该类控制反转给spring(交给spring管理了)。

@component后期分三个:@controller、@service、@repository由于后期将针对不同层上的属性进行不同注解

属性注解
  1. 普通属性注解:就是@value(“值内容”)就ok了
  2. 引用类型注解: 可以通过@autowired(自动根据类型来依赖注入其内容的值);区别于以前在配置文件中按照名称name来注入。但是类型注入的话,有时候同一个接口类型的话,就不确定具体哪一个实现类的注入,所以常用@qualifier来明确具体类的id的方式来注入。
  3. 上面两个才实现了按名称的方式来注入的注解方式,有点不太方便,所以又出现一个便捷的@resource注解。实际开发中常用@resource(name=“”)按照名称来注入的注解方式。
    类似于< property name=“属性名” ref=“引用类的id名” > 属性注入这边,属性name开头可以不分大小写。
    (< property name=“age” value=“22”>< /property > name内容是类中属性名,开头不分大小写)
    案例:
@Component(value="sun_car")public class sun_car implements car {	@Override	public void run() {		System.out.println("第二辆车运行");	}	@Override	public void start() {		System.out.println("第二辆车开始");	}	@Override	public void stop() {		System.out.println("第二辆车停止");	}}========================================@Component(value="mycar") //相当于
public class mycar implements car { @Value("sunxiang") private String name; @Resource(name="sun_car") private car car; public void start() { System.out.println("2....."+car.getClass()); car.start(); System.out.println(name+"我的车启动了1。。。"); } public void run() { System.out.println(name+"我的车上路了1。。。"); } public void stop() { System.out.println(name+"我的车熄火了1。。。"); }}=============================================public class car_test {@Testpublic void demo2() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext.xml"); car car = (car)context.getBean("mycar"); System.out.println("1......"+car.getClass()); car.start();}}--------------------结果:1......class com.sun.annotaion.mycar2.....class com.sun.annotaion.sun_car第二辆车开始sunxiang我的车启动了1。。。
  1. bean生命周期的注解(作用于方法上的注解)——初始化注解:@PostConstruct(在作为初始化的方法上注解标识就ok了,没有其他内容奥!)。销毁注解:@PreDestroy(在某个作为销毁方法上面注解)
  2. bean的作用范围的注解(作用于类上的注解):@Scope(“singleton/prototype”)
@Testpublic void demo2() {	ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext.xml");	car car1 = (car)context.getBean("mycar");	System.out.println(car1);		car car2 = (car)context.getBean("mycar");	System.out.println(car2);	}	----------------------------------	结果:       由于工厂类默认是单例模式创建bean	com.sun.annotaion.mycar@1f1c7bf6	com.sun.annotaion.mycar@1f1c7bf6

IOC的xml和注解的比较

应用场景不同

(1)xml:可以应用于任何场景、且结构清晰维护方便,直接可以通过xml配置文件可以了解类的整个结构(清晰类中用到哪些属性了,一目了然)。

(2)注解:如果以些类不是自己写的,直接打包成源码的那些,无法进入源码进行注解设置。好处是:开发方便。
(3)xml和注解结合使用:xml管理bean(整个结构中bean很清晰),注解注入属性(省去set方法,类中很清晰。)

AOP基于aspectj注解方式

一.常见AOP的xml的方式
//下面的配置就是完成spring自动动态代理方式,由spring来完成方法的增强。//注意虽然spring自动完成代理了,但不能忘记底层动态代理实现的原理奥!!!!!!!只对待增强的方法增强,其他原样输出 
!!!!//前置通知。特点:可以在通知方法内获得切入点信息 !!!!!!//特别注意环绕通知,要将待增强方法传入环绕通知内中。
二 AOP注解的前期准备

(1)同样引入jar包

在这里插入图片描述
(2)编写好目标类 和 切面类(通知类,里面是增强的方法)

//目标类public class mycar  {	public void start() {		System.out.println("我的车启动了2。。。");		}	public void run() {		System.out.println("我的车上路了2。。。");			}	public void stop() {		System.out.println("我的车熄火了2。。。");	}}====================================//切面类(我习惯认为是通知类(增强方法的封装类))这个类很重要!!!!!!!public class enhance {public void enhan() {		System.out.println("加速度2。。。。");}}

(3)注意上面的类上没有注解,说明这边bean的管理没有使用注解管理方式

//这部分仅仅是试验AOP注解,所以IOC的注解没有使用。还是通过配置文件管理bean对象

(4)下面开始通过AOP注解来对目标类进行增强

同样和IOC注解那样,要在配置文件中(开启注解模式认证);ioc是开启IOC组件注解扫描,AOP这边要开启:

(5)开启了通过注解的方式来实现aop过程了,那么就可以直接通过注解来完成方法的增强了,不用配置文件中 <aop:config > </aop:config>内进行动态代理的各种配置了。

注意:!!! 前面分析过AOP面向切面编程(方法增强)中:两个关键点必须要明确

  • 哪个待增强类的哪个方法
  • 通知,就是增强的内容(方法)

这两个关键点都在切面类上体现

(6)注解符号:

@Aspect
@Before(value=“execution(表达式来表示哪个类的哪个方法)”)

(7)AOP注解入门测试:在切面上注解AOP的两个关键点:哪个类哪个方法要增强、通知(增强的内容/方法)

//通知类@Aspectpublic class enhance {	@Before(value="execution(* com.sun.annotaion2.mycar.run())")public void enhan() {	System.out.println("加速度2。。。。");}}

(8)AOP注解方式,只在切面类上注解设置,目标类上没有改变。即:

//目标类上和xml一样没有任何改动public class mycar  {	public void start() {		System.out.println("我的车启动了2。。。");		}	public void run() {		System.out.println("我的车上路了2。。。");			}	public void stop() {		System.out.println("我的车熄火了2。。。");	}}

(9)注解方式的AOP实现的增强结果显示:最终完成对目标类mycar的run()方法的增强。源代码没任何改变。

public class car_test2 {	@Test	public void demo2() {		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext2.xml");	mycar car1 = (mycar)context.getBean("mycar");				car1.run();	}}-------------------------------------测试结果:加速度2。。。。我的车上路了2。。。

(10)测试类中可以结合spring的junit测试方式来表示:要引入spring-junit结合的jar包;对比上面测试代码,省略了工厂对象的创建。而且mycar的bean对象一属性注入的方式产生,不用写工厂对象的getbean获取,节省代码。

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:applicationcontext2.xml")public class car_test2 {	@Resource(name="mycar")	private mycar car1;@Testpublic void demo2() {		car1.run();}}-------------------------------------测试结果:加速度2。。。。我的车上路了2。。。

对比下AOP的xml方式和注解方式:

  • 首先AOP关键点:切入点通知
  • 本质:要在切入点上添加通知;通俗说就是在哪个类的哪个方法上通过AOP方式进行增强。

中心思想:就是想在指定类的指定方法上进行增强。

(1)原始思想:创建类的时候,在方法中直接调用增强的方法。
(2)继承思想:将增强的方法封装,然后继承这个类,在方法中调用增强的方法,避免原始思想在所有要增强的类中都创建增强方法,然后调用增强方法。
(3)动态代理思想:只写一个动态代理类,然后传入要增强的类,并针对这个类中指定方法进行增强,任何增强的改变只在代理类中完成,不用像继承那样,增强方法的添加和删除的话,要所有类上都去掉继承。
(4)动态代理之后演进成AOP了(底层实现),接着又由Aspectj规范封装了,最后spring又引入Aspectj的aop,所有核心就是类似于动态代理奥!!!!所有出现两个关键点:哪个类的哪个方法要增强,增强的方法
(5)对于两个关键点:Spring的AOP的xml配置体现:

//切入点,就是明确哪个类的哪个方法
//明确增强的内容(方法)
=========================================//切面类就是基本的增强方法的封装public class enhance { public void enhan() { System.out.println("加速度2。。。。"); }}

(6)对于Spring的AOP的注解体现: 对比配置文件形式,就是将aop:config</aop:config>内属性设置直接在切面类上注解设置(体现)了。还是设置两个关键点:具体哪个类的哪个方法,还有增强的内容(方法)

========================================//注解主要是在切面类中注解设置的。@Aspectpublic class enhance { @Before(value="execution(* com.sun.annotaion2.mycar.run())")public void enhan() { System.out.println("加速度2。。。。");}}

(7)上面5和6,AOP的配置的测试结果都一样

package com.sun.annotaion2;import javax.annotation.Resource;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:applicationcontext2.xml")public class car_test2 {	@Resource(name="mycar")	private mycar car1;@Testpublic void demo2() {		car1.run();}}==================================测试结果:加速度2。。。。我的车上路了2。。。

(8)同样后置通知配置的话,注解的话直接在通知方法上注解就可以了,不用到配置文件下那样配置。直接通知方法上@AfterReturning(value=“execution(* com.sun.annotaion2.mycar.run())”)就ok了。

环绕通知的注解和xml比较:

========================================@Aspectpublic class enhance { private Object proceed;@Before(value="execution(* com.sun.annotaion2.mycar.run())")public void enhan() { System.out.println("加速度2。。。。");}@AfterReturning(value="execution(* com.sun.annotaion2.mycar.run())")public void after() { System.out.println("太快了,注意减速2。。。。");}@Around(value="execution(* com.sun.annotaion2.mycar.stop())")//环绕通知相比于前置和后置,要特殊点,注解只在方法上注解,其他环绕方法内容和配置文件方式一样,没有改变public Object around(ProceedingJoinPoint joinpoint) throws Throwable { System.out.println("环绕前。。。。。"); proceed = joinpoint.proceed(); System.out.println("环绕后。。。。。"); return proceed;}/*//环绕通知的注解要注意一下,原本没注解的方式也和其他前置后置不同@Around("MyAspectAnno.pointcut3()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("环绕前通知==========");Object obj = joinPoint.proceed();System.out.println("环绕后通知==========");return obj;}*/}

小结

IOC注解中特别关注:类的注解(bean对象的管理) 类中属性的注解(属性注入)

AOP注解中特别关注:切入点(哪个类的哪个方法)的注解 通知的注解,都是在切面类上注解这两个关键信息的。特别是哪个类哪个方法别忘了,这表示通知要切入的目的位置奥,如前置注解:就是表示这个通知要切入的位置mycar类下的run()方法、之前切入

@Before(value="execution(* com.sun.annotaion2.mycar.run())")public void enhan() {	System.out.println("加速度2。。。。");}

转载地址:http://chdxi.baihongyu.com/

你可能感兴趣的文章
来玩下go的http get
查看>>
队列和栈的本质区别
查看>>
matlab中inline的用法
查看>>
如何用matlab求函数的最值?
查看>>
Git从入门到放弃
查看>>
java8采用stream对集合的常用操作
查看>>
EasySwift/YXJOnePixelLine 极其方便的画出真正的一个像素的线
查看>>
Ubuntu Linux系统下apt-get命令详解
查看>>
ubuntu 16.04 下重置 MySQL 5.7 的密码(忘记密码)
查看>>
Ubuntu Navicat for MySQL安装以及破解方案
查看>>
HTTPS那些事 用java实现HTTPS工作原理
查看>>
oracle函数trunc的使用
查看>>
MySQL 存储过程或者函数中传参数实现where id in(1,2,3,...)IN条件拼接
查看>>
java反编译
查看>>
Class.forName( )你搞懂了吗?——转
查看>>
jarFile
查看>>
EJB与JAVA BEAN_J2EE的异步消息机制
查看>>
数学等于号是=那三个横杠是什么符
查看>>
HTTP协议详解
查看>>
java多线程中的join方法详解
查看>>