Spring使用注解配置bean
1.使用注解配置bean步骤
(1.在配置文件中添加context命名空间
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd"
(2.添加aop jar包
(3.扫描注解
配置文件中添加:
<context:component-scan base-package="包名"></context:component-scan>
会扫描指定的包名下的所有子孙包
2.注解介绍
(1.只能加在类上 如果没有指定bean名字 默认是以小写开头的类名
为其指定名字: Component("name")
Component
Service 对应Service业务逻辑层
Controller 对应Action Servlet
Repository 对应数据库相关(Dao)
下面三个是Component的衍生标签 作用是一样的 但是这三个标签更加语义化
更符合 JavaEE分层思想
(2.使用以上注解配置bean时 可以使用@Value("值")配置bean属性的值
@Value() 可以写在属性上 也可以写在set方法上
但是写在属性上会破坏对象的封装性 建议写在set方法上
(3.Scope注解 用来控制bean的作用域 例:@Scope(scopeName="singleton")
Scope注解也是写在类上 有下列四种
singleton 单例
prototype 多例
request session 与 request和session一样
(4.@Autowired 自动装配 可以将容器中对应的bean自动注入到属性中
单独使用时 该注解下的bean对象 必须是Spring容器中有的
而且名字必须相同
@Qualifier(" ") 如果容器中有多个对应类型的bean 可以使用@Qualifier
指定具体注入哪一个 一般和Autowired搭配使用
(5.@Resource("name") 功能与上面两个注解搭配使用效果一样
但是属于手动装配 告诉Spring 把哪一个bean注入进来
(6.PostConstructor 加在方法上 对象构造后立即执行(相当于添加初始化方法)
preDestory 加在方法上 对象销毁前执行(相当于添加销毁方法)
Spring与Junit的整合
1.在测试环境需要创建Spring容器 为了方便在测试环境中不用每个测试方法都去获取容器
所以出现了Spring与Junity的整合
方式一:
(1.导入jar包spring-test-5.0.5.RELEASE.jar
(2.在测试类上添加:
// 运行测试时 会自动创建Spring容器
@RunWith(SpringJUnit4ClassRunner.class) 运行测试时 会自动创建Spring容器
// 指定配置文件
@ContextConfiguration("classpath:applicationContext.xml")
方式二:
(1.导入jar包spring-test-5.0.5.RELEASE.jar
(2.利用Junit的@Befor与@After
public class SpringTest {
ClassPathXmlApplicationContext ac;
@After
public void after() {
System.out.println("测试代码后");
ac.close();
}
@Before
public void before() {
System.out.println("测试代码前");
ac = new ClassPathXmlApplicationContext("applicationContext.xml");
}
@Test
public void method1() {
System.out.println(ac.getBean("per"));
}
@Test
public void method2() {
System.out.println(ac.getBean("person1"));
}
}
Spring的AOP
1.AOP Aspect Oriented Programming
全程面向切面编程
是一种编程思想 就像OOP一样
OOP的核心就是类和对象
AOP的核心是切面
其实AOP说的简单点就是将公共代码进行抽取 然后集中编写
例如:之前使用过的过滤器 拦截器 都是AOP思想
AOP名词解释
Joinpoint连接点 可以增强对象
Pointcut切入点 需要进行增强方法
Advice 通知、增强代码
Target 目标对象 被代理对象
Weaving 织入 将通知应用到链接点的过程
代理 代理对象
切面 切入点+通知
Spring是如何实现AOP(就是把增强代码插入原有代码)
1.动态代理
A对象需要被代理
B对象代理A
本来直接调用 A对象的方法
现在换个方式 先调用B对象 B再去调用A对象
被代理对象(A)必须有实现某个接口
注意: 没有实现任何接口的对象无法代理 不能增强
2.cglib
A对象需要被代理
B对象代理A
实现代码增强的原理
会自动生成被代理类的子类对象
生成一个A类的子类
在子类中对代码进行增强
然后调用父类的原有代码
注意: 被final修饰的类不能别代理 不能进行增强
如果某个类既没有接口 又被final修饰 SpringAOP就搞不定
这时AspectJ就发挥作用了
用Spring的AOP实现 对方法的调用进行记录 生成记录日志
1.思路:
首先明确采用AOP
就是对所有的方法进行增强
使其具备打印日志的功能
方式一
(1.在配置文件中添加aop和context约束
(2.配置 配置文件
<bean name="advice" class="com.lanou.DaoImpl.MyAdvice"></bean>
<aop:config>
<!--创建切入点-->
<aop:pointcut expression="execution(* com.lanou.DaoImpl.UserDaoImpl.*(..))" id="point"/>
<!--将通知织入切点-->
<aop:advisor advice-ref="advice" pointcut-ref="point"/>
</aop:config>
<!-- 开启扫描注解 -->
<context:component-scan base-package="com.
xxx"></context:component-scan>
(3.编写通知类
public class MyAdvice implements MethodBeforeAdvice,AfterReturningAdvice{
// 前置通知(前置增强)
// 参数1 Method 要调用的原始方法
// 参数2 Obj[] 方法的参数
// 参数3 Object 被代理对象 真正要执行方法的对象
@Override
public void before(Method method, Object[] args, Object target)
throws Throwable {
System.out.println(new Date() + " " + target +
"执行了" + method.getName() + "参数:" +Arrays.toString(args));
// 执行方法
//Object object = method.invoke(target, args);
}
// 后置通知
@Override
public void afterReturning(Object returnValue, Method method,
Object[] args, Object target) throws Throwable {
System.out.println(new Date() + " " + target + "执行了" +
method.getName() + "参数:" +Arrays.toString(args) +
"返回值" + returnValue);
// 执行方法
//Object object = method.invoke(target, args);
}
}
方式二
(1.在配置文件中添加aop和context约束
(2.配置 配置文件
<bean name="aroundadvice" class="com.lanou.DaoImpl.MyAroundAdvice"></bean>
<aop:config>
<aop:pointcut expression="execution(* com.lanou.DaoImpl.UserDaoImpl.*(..))" id="point"/>
<aop:advisor advice-ref="aroundadvice" pointcut-ref="point"/>
</aop:config>
<!-- 开启扫描注解 -->
<context:component-scan base-package="com.xxx"></context:component-scan>
(3.编写通知类
public class MyAroundAdvice implements MethodInterceptor{
// 环绕通知 方法执行前后都可以知道
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Object target = invocation.getThis();
Object[] arguments = invocation.getArguments();
Method method = invocation.getMethod();
System.out.println("环绕增强前");
// 环绕通知 不会自动调用原始方法
Object result = method.invoke(target, arguments);
System.out.println("环绕增强后");
System.out.println(result);
return result;
}
}