使用注解开发
- 类的注入
@Component //等价于<bean id="user" class="com.lyc.pojo.User"/>
//组件,放在类上,说明这个类被Spring管理了
<!--指定要扫描的包,包下的注解就会生效-->
<context:component-scan base-package="com.lyc.pojo"/>
-
属性的注入
放在属性上方
@value
@Value("lyc") private String name; //等价于 <property name>
- @Component会按照mvc三层架构分层,实质上都是组件的装配
- dao @Repository
- service @Service
- controller @Controller
@Scope("singleton") //配置bean的作用域,声明这个类为单例模式
//等价于 bean scope标签
xml配置复杂的东西,注解适用于配置简单的东西
使用JavaConfig配置spring
不使用xml去配置
Javaconfig注册类到Spring
@Configuration
public class UserConfig {
@Bean
public User getUser(){
return new User();
}
}
测试类
@Test
public void test2(){
ApplicationContext context = new AnnotationConfigApplicationContext(UserConfig.class);
User user = (User) context.getBean("getUser");
System.out.println(user.getName());
}
}
代理模式
分类
- 静态代理
- 动态代理
静态代理
- 抽象角色:一般使用接口或者抽象类
- 真实角色:被代理的角色
- 代理角色:代理真实角色,有一些附属操作
- 客户:真实使用资源的人
例子
接口
public interface Rent {
public void rent();
}
真实角色
public class Host implements Rent{
public void rent() {
System.out.println("租房成功");
}
}
代理角色
public class Proxy implements Rent{
private Host host;
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
public void rent() {
host.rent();
}
}
客户
public class Client {
public static void main(String[] args) {
Host host = new Host();
Proxy proxy = new Proxy(host);
proxy.rent(); //客户直接面对的是proxy
}
}
好处
- 使得真实角色的操作更加纯粹,不用去关注一些公共的业务
- 公共业务交给代理角色
- 公共业务发生扩展的时候,方便集中管理
静态代理缺点
- 一个真实角色会产生一个代理角色,代码量会上去
动态代理
使用反射动态加载类,减少代码量
- 抽象角色:一般使用接口或者抽象类
- 真实角色:被代理的角色
- 代理角色:代理真实角色,有一些附属操作,动态生成代理类
- 客户:真实使用资源的人
动态分类
- 基于接口的动态代理
- 基于类的动态代理
Proxy:代理
InvocationHandler:产生代理类
万能工具类
//自动生产动态类
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Object target;
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
//生成得到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//处理代理实例,并返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
Object result = method.invoke(target, args);
return result;
}
public void seeHouse(){
System.out.println("看房子");
}
}
通过传入对象不同,来分别加载对应的类,产生对应的代理类!
一个动态代理类代理一个接口
AOP
面向切面编程,通过预编译方式和运行期动态代理程序功能的统一维护的一种技术
在Spring中AOP
提供声明式事务;允许用户自定义切面
- 横切关注点:跨越应用程序多个模块的方法或功能。即是与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点,如日志,安全,缓存,事务等等
- 切面(Aspect):横切关注点被模块化的特殊对象,比如日志类
- 通知(Adivice):切面必须要完成的工作,他是切面类中的一个方法,比如日志类中的方法
- 目标(Target):被通知对象。一个接口或一个方法
- 代理(Proxy):向目标对象应用通知之后创建的对象。比如生成的代理类
- 切入点(PointCut):切面通知执行的地点的定义,比如invoke方法
- 连接点(JointPoint):与切入点匹配的执行点
Spring5种类型的通知
使用Spring原生api接口实现aop
一添加配置
<!--使用原生API接口-->
<!--配置aop:需要导入aop约束-->
<aop:config>
<!--切入点 expression:表达式,execution(要执行的位置!)-->
<!--限定符,类名,类下面的方法名,参数-->
<aop:pointcut id="pointcut" expression="execution(public * com.lyc.service.UserServiceImpl.* (..))"/>
<!--执行环绕-->
<aop:advisor advice-ref="log" pointcut="pointcut" />
<aop:advisor advice-ref="afterLog" pointcut="pointcut" />
</aop:config>
Userservice接口
public interface UserService {
void add();
void delete();
void update();
void select();
}
接口实现类
@Component
public class UserServiceImpl implements UserService{
public void add() {
System.out.println("增加了一个用户");
}
public void delete() {
System.out.println("删除了一个用户");
}
public void update() {
System.out.println("修改了一个用户");
}
public void select() {
System.out.println("查询了一个用户");
}
}
前置类型操作
@Component
public class Log implements MethodBeforeAdvice {
/**
* method:要执行的目标对象的方法
* args:参数
* target:目标对象
*/
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName());
}
}
后置返回操作
@Component
public class AfterLog implements AfterReturningAdvice {
// o:返回值 objects:参数 o1:目标对象
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println(method.getName()+"返回结果为"+o);
}
}
测试类
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserService userservice = (UserService) context.getBean("userServiceImpl"); //代理接口,但要获得接口实现类的bean
userservice.add();
}
}
使用自定义类去实现aop
配置文件
<!--方式二:自定义类-->
<aop:config>
<aop:aspect ref="diyPointCut">
<aop:pointcut id="pointcut" expression="execution(* com.lyc.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after method="after" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
自定义类
@Component
public class DiyPointCut {
public void before(){
System.out.println("方法执行前");
}
public void after(){
System.out.println("方法执行后");
}
}
注解实现AOP
配置文件
<aop:aspectj-autoproxy/>
切面类
//使用注解方式实现AOP
@Component
@Aspect
public class AnnotationPointCut {
@Before("execution(* com.lyc.service.UserServiceImpl.*(..))") //定义切入点
public void before(){
System.out.println("方法执行前");
}
}
void after(){
System.out.println("方法执行后");
}
}
注解实现AOP
配置文件
<aop:aspectj-autoproxy/>
切面类
//使用注解方式实现AOP
@Component
@Aspect
public class AnnotationPointCut {
@Before("execution(* com.lyc.service.UserServiceImpl.*(..))") //定义切入点
public void before(){
System.out.println("方法执行前");
}
}